mirror of
https://github.com/wrwrabbit/Partisan-Telegram-Android.git
synced 2026-10-19 09:35:24 +00:00
update to 13.0.1 (7166)
This commit is contained in:
parent
5e56d34341
commit
368b6b7fd3
76 changed files with 4837 additions and 2230 deletions
|
|
@ -39,7 +39,6 @@ CMD mkdir -p /home/source/TMessagesProj/build/outputs/apk && \
|
|||
cp -R /home/source/. /home/gradle && \
|
||||
cd /home/gradle && \
|
||||
gradle --parallel \
|
||||
:TMessagesProj_App:bundleBundleAfat_SDK23Release \
|
||||
:TMessagesProj_App:bundleBundleAfatRelease \
|
||||
:TMessagesProj_AppStandalone:assembleAfatStandalone \
|
||||
:TMessagesProj_App:assembleAfatRelease \
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ public class AppGlobalConfig {
|
|||
public final ConfigStringSet botAllowedSuffixes = ofStringSet("bot_allowed_suffixes", Collections.singleton("bot"));
|
||||
|
||||
public final ConfigBoolean walletAvailable = ofBoolean("wallet_available", BuildVars.DEBUG_VERSION);
|
||||
public final ConfigBoolean walletPaidMessageRecipientMessageAmountCheck = ofBoolean("wallet_paid_message_recipient_message_amount_check", true);
|
||||
public final ConfigLong walletTransferMinNanos = ofLong("wallet_transfer_min_nanos", 100_000_000);
|
||||
public final ConfigLong walletGaslessMinNanos = ofLong("wallet_gasless_min_nanos", 100_000_000);
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import com.google.gson.stream.JsonWriter;
|
|||
|
||||
import org.telegram.messenger.time.FastDateFormat;
|
||||
import org.telegram.messenger.video.MediaCodecVideoConvertor;
|
||||
import org.telegram.tgnet.NativeByteBuffer;
|
||||
import org.telegram.tgnet.TLObject;
|
||||
import org.telegram.tgnet.TLRPC;
|
||||
import org.telegram.ui.Components.AnimatedFileDrawable;
|
||||
|
|
@ -44,6 +45,7 @@ import java.util.ArrayList;
|
|||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class FileLog {
|
||||
private OutputStreamWriter streamWriter = null;
|
||||
|
|
@ -88,19 +90,51 @@ public class FileLog {
|
|||
|
||||
private static Gson gson;
|
||||
private static ExclusionStrategy exclusionStrategy;
|
||||
private static HashSet<String> excludeRequests;
|
||||
// Dumps are best-effort diagnostics: never backpressure the network thread.
|
||||
private static final int MAX_PENDING_PROTOCOL_DUMPS = 8;
|
||||
private static final AtomicInteger pendingProtocolDumps = new AtomicInteger();
|
||||
|
||||
private static void postProtocolDump(Runnable dump) {
|
||||
if (pendingProtocolDumps.incrementAndGet() > MAX_PENDING_PROTOCOL_DUMPS) {
|
||||
pendingProtocolDumps.decrementAndGet();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
FileLog logger = getInstance();
|
||||
if (logger.logQueue == null) {
|
||||
pendingProtocolDumps.decrementAndGet();
|
||||
return;
|
||||
}
|
||||
logger.logQueue.postRunnable(() -> {
|
||||
try {
|
||||
dump.run();
|
||||
} catch (Throwable e) {
|
||||
// Application callbacks may have changed Java fields/collections
|
||||
// by now. A failed debug dump must not affect request processing.
|
||||
Log.e(tag, "Unable to serialize asynchronous protocol dump", e);
|
||||
} finally {
|
||||
pendingProtocolDumps.decrementAndGet();
|
||||
}
|
||||
});
|
||||
} catch (Throwable e) {
|
||||
pendingProtocolDumps.decrementAndGet();
|
||||
Log.e(tag, "Unable to queue protocol dump", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void dumpResponseAndRequest(int account, TLObject request, TLObject response, TLRPC.TL_error error, long requestMsgId, long startRequestTimeInMillis, int requestToken) {
|
||||
if (!BuildVars.DEBUG_PRIVATE_VERSION || !BuildVars.LOGS_ENABLED || request == null) {
|
||||
return;
|
||||
}
|
||||
String requestSimpleName = request.getClass().getSimpleName();
|
||||
checkGson();
|
||||
|
||||
if (excludeRequests.contains(requestSimpleName) && error == null) {
|
||||
if (error == null && ("TL_upload_getFile".equals(requestSimpleName) || "TL_upload_getWebFile".equals(requestSimpleName))) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
long time = System.currentTimeMillis();
|
||||
long requestingTime = time - startRequestTimeInMillis;
|
||||
boolean hasError = error != null;
|
||||
postProtocolDump(() -> {
|
||||
checkGson();
|
||||
String req = "req -> " + requestSimpleName + " : " + gson.toJson(request);
|
||||
String res = "null";
|
||||
if (response != null) {
|
||||
|
|
@ -108,71 +142,56 @@ public class FileLog {
|
|||
} else if (error != null) {
|
||||
res = "err -> " + error.getClass().getSimpleName() + " : " + gson.toJson(error);
|
||||
}
|
||||
String finalRes = res;
|
||||
long time = System.currentTimeMillis();
|
||||
FileLog.getInstance().logQueue.postRunnable(() -> {
|
||||
try {
|
||||
String metadata = "requestMsgId=" + requestMsgId + " requestingTime=" + (System.currentTimeMillis() - startRequestTimeInMillis) + " request_token=" + requestToken + " account=" + account;
|
||||
FileLog.getInstance().tlStreamWriter.write(getInstance().dateFormat.format(time) + " " + metadata);
|
||||
FileLog.getInstance().tlStreamWriter.write("\n");
|
||||
FileLog.getInstance().tlStreamWriter.write(req);
|
||||
FileLog.getInstance().tlStreamWriter.write("\n");
|
||||
FileLog.getInstance().tlStreamWriter.write(finalRes);
|
||||
FileLog.getInstance().tlStreamWriter.write("\n\n");
|
||||
FileLog.getInstance().tlStreamWriter.flush();
|
||||
try {
|
||||
String metadata = "requestMsgId=" + requestMsgId + " requestingTime=" + requestingTime + " request_token=" + requestToken + " account=" + account;
|
||||
FileLog logger = getInstance();
|
||||
logger.tlStreamWriter.write(logger.dateFormat.format(time) + " " + metadata);
|
||||
logger.tlStreamWriter.write("\n");
|
||||
logger.tlStreamWriter.write(req);
|
||||
logger.tlStreamWriter.write("\n");
|
||||
logger.tlStreamWriter.write(res);
|
||||
logger.tlStreamWriter.write("\n\n");
|
||||
logger.tlStreamWriter.flush();
|
||||
|
||||
if (error != null) {
|
||||
Log.e(mtproto_tag, metadata);
|
||||
Log.e(mtproto_tag, req);
|
||||
Log.e(mtproto_tag, finalRes);
|
||||
Log.e(mtproto_tag, " ");
|
||||
} else {
|
||||
Log.d(mtproto_tag, metadata);
|
||||
Log.d(mtproto_tag, req);
|
||||
Log.d(mtproto_tag, finalRes);
|
||||
Log.d(mtproto_tag, " ");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
} catch (Throwable e) {
|
||||
FileLog.e(e, BuildVars.DEBUG_PRIVATE_VERSION);
|
||||
}
|
||||
int priority = hasError ? Log.ERROR : Log.DEBUG;
|
||||
Log.println(priority, mtproto_tag, metadata);
|
||||
Log.println(priority, mtproto_tag, req);
|
||||
Log.println(priority, mtproto_tag, res);
|
||||
Log.println(priority, mtproto_tag, " ");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void dumpUnparsedMessage(TLObject message, long messageId, int account) {
|
||||
if (!BuildVars.DEBUG_PRIVATE_VERSION || !BuildVars.LOGS_ENABLED || message == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
long time = System.currentTimeMillis();
|
||||
boolean skipGson = gsonDisabled;
|
||||
postProtocolDump(() -> {
|
||||
checkGson();
|
||||
getInstance().dateFormat.format(System.currentTimeMillis());
|
||||
String messageStr = "receive message -> " + message.getClass().getSimpleName() + " : " + (gsonDisabled ? message : gson.toJson(message));
|
||||
String res = "null";
|
||||
long time = System.currentTimeMillis();
|
||||
FileLog.getInstance().logQueue.postRunnable(() -> {
|
||||
try {
|
||||
String metadata = getInstance().dateFormat.format(time) + " msgId=" + messageId + " account=" + account;
|
||||
String messageStr = "receive message -> " + message.getClass().getSimpleName() + " : " + (skipGson ? message : gson.toJson(message));
|
||||
try {
|
||||
FileLog logger = getInstance();
|
||||
String metadata = logger.dateFormat.format(time) + " msgId=" + messageId + " account=" + account;
|
||||
logger.tlStreamWriter.write(metadata);
|
||||
logger.tlStreamWriter.write("\n");
|
||||
logger.tlStreamWriter.write(messageStr);
|
||||
logger.tlStreamWriter.write("\n\n");
|
||||
logger.tlStreamWriter.flush();
|
||||
|
||||
FileLog.getInstance().tlStreamWriter.write(metadata);
|
||||
FileLog.getInstance().tlStreamWriter.write("\n");
|
||||
FileLog.getInstance().tlStreamWriter.write(messageStr);
|
||||
FileLog.getInstance().tlStreamWriter.write("\n\n");
|
||||
FileLog.getInstance().tlStreamWriter.flush();
|
||||
|
||||
Log.d(mtproto_tag, "msgId=" + messageId + " account=" + account);
|
||||
Log.d(mtproto_tag, messageStr);
|
||||
Log.d(mtproto_tag, " ");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
} catch (Throwable e) {
|
||||
}
|
||||
Log.d(mtproto_tag, "msgId=" + messageId + " account=" + account);
|
||||
Log.d(mtproto_tag, messageStr);
|
||||
Log.d(mtproto_tag, " ");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static boolean gsonDisabled;
|
||||
private static volatile boolean gsonDisabled;
|
||||
public static void disableGson(boolean disable) {
|
||||
gsonDisabled = disable;
|
||||
}
|
||||
|
|
@ -202,11 +221,6 @@ public class FileLog {
|
|||
privateFields.add("FLAG_" + i);
|
||||
}
|
||||
|
||||
//exclude file loading
|
||||
excludeRequests = new HashSet<>();
|
||||
excludeRequests.add("TL_upload_getFile");
|
||||
excludeRequests.add("TL_upload_getWebFile");
|
||||
|
||||
exclusionStrategy = new ExclusionStrategy() {
|
||||
|
||||
@Override
|
||||
|
|
@ -219,7 +233,7 @@ public class FileLog {
|
|||
|
||||
@Override
|
||||
public boolean shouldSkipClass(Class<?> clazz) {
|
||||
return clazz.isInstance(DispatchQueue.class) || clazz.isInstance(AnimatedFileDrawable.class) || clazz.isInstance(ColorStateList.class) || clazz.isInstance(Context.class);
|
||||
return NativeByteBuffer.class.isAssignableFrom(clazz) || clazz.isInstance(DispatchQueue.class) || clazz.isInstance(AnimatedFileDrawable.class) || clazz.isInstance(ColorStateList.class) || clazz.isInstance(Context.class);
|
||||
}
|
||||
};
|
||||
gson = new GsonBuilder()
|
||||
|
|
@ -278,6 +292,10 @@ public class FileLog {
|
|||
field.setAccessible(true);
|
||||
try {
|
||||
Object value = field.get(src);
|
||||
// Native buffers can already have been returned to their pool.
|
||||
if (value instanceof NativeByteBuffer) {
|
||||
continue;
|
||||
}
|
||||
if (value != null) {
|
||||
Class clazz = value.getClass();
|
||||
if (clazz.isInstance(DispatchQueue.class) || clazz.isInstance(AnimatedFileDrawable.class) || clazz.isInstance(ColorStateList.class) || clazz.isInstance(Context.class)) {
|
||||
|
|
|
|||
|
|
@ -5952,6 +5952,8 @@ public class MessageObject {
|
|||
}
|
||||
if (isOut()) {
|
||||
messageTextShort = AndroidUtilities.replaceTags(LocaleController.formatString(R.string.WalletActionSentGramsShort, GramWallet.formatGramsWithUnit(action.amount)));
|
||||
} else if (UserObject.isService(DialogObject.getPeerDialogId(messageOwner.peer_id))) {
|
||||
messageTextShort = AndroidUtilities.replaceTags(LocaleController.formatString(R.string.WalletActionReceivedGramsSomeone, GramWallet.formatGramsWithUnit(action.amount)));
|
||||
} else {
|
||||
messageTextShort = AndroidUtilities.replaceTags(LocaleController.formatString(R.string.WalletActionReceivedGrams, GramWallet.formatGramsWithUnit(action.amount)).replace("un1", "").trim());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ public class TLParseException extends RuntimeException {
|
|||
final TLParseException tlParseException = new TLParseException(message);
|
||||
|
||||
FileLog.e(tlParseException, constructorId != 0xcd78e586);
|
||||
if (BuildConfig.DEBUG_VERSION && constructorId != 0xcd78e586 && constructorId != 0xd18be2ef) {
|
||||
if (BuildConfig.DEBUG_VERSION && constructorId != 0xcd78e586 && constructorId != 0xd18be2ef && constructorId != 0xf35c6d01) {
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
NotificationCenter.getGlobalInstance()
|
||||
.postNotificationName(NotificationCenter.tlSchemeParseException, tlParseException);
|
||||
|
|
|
|||
|
|
@ -2416,6 +2416,7 @@ public class ActionBarMenuItem extends FrameLayout {
|
|||
public CharSequence text;
|
||||
public boolean dismiss, needCheck;
|
||||
public View viewToSwipeBack;
|
||||
private Utilities.Callback0Return<View> swipeBackViewFactory;
|
||||
public int textSizeDp;
|
||||
|
||||
private View view;
|
||||
|
|
@ -2512,6 +2513,10 @@ public class ActionBarMenuItem extends FrameLayout {
|
|||
layoutParams.width = LayoutHelper.MATCH_PARENT;
|
||||
layoutParams.height = AndroidUtilities.dp(48);
|
||||
cell.setLayoutParams(layoutParams);
|
||||
if (swipeBackViewFactory != null) {
|
||||
viewToSwipeBack = swipeBackViewFactory.run();
|
||||
swipeBackViewFactory = null;
|
||||
}
|
||||
int swipeBackIndex = parent.popupLayout.addViewToSwipeBack(viewToSwipeBack);
|
||||
cell.openSwipeBackLayout = () -> {
|
||||
if (parent.popupLayout.getSwipeBack() != null) {
|
||||
|
|
@ -2608,6 +2613,11 @@ public class ActionBarMenuItem extends FrameLayout {
|
|||
public Item lazilyAddSwipeBackItem(int icon, Drawable iconDrawable, String text, View viewToSwipeBack) {
|
||||
return putLazyItem(Item.asSwipeBackItem(icon, iconDrawable, text, viewToSwipeBack));
|
||||
}
|
||||
public Item lazilyAddSwipeBackItem(int icon, Drawable iconDrawable, String text, Utilities.Callback0Return<View> viewFactory) {
|
||||
Item item = Item.asSwipeBackItem(icon, iconDrawable, text, null);
|
||||
item.swipeBackViewFactory = viewFactory;
|
||||
return putLazyItem(item);
|
||||
}
|
||||
public Item lazilyAddSubItem(int id, int icon, CharSequence text) {
|
||||
return lazilyAddSubItem(id, icon, null, text, true, false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -219,7 +219,10 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
}
|
||||
|
||||
public void setSpoilersSuppressed(boolean s) {
|
||||
walletActionLayout.setSpoilersSuppressed(s);
|
||||
spoilersSuppressed = s;
|
||||
if (walletActionLayout != null) {
|
||||
walletActionLayout.setSpoilersSuppressed(s);
|
||||
}
|
||||
for (SpoilerEffect eff : spoilers) {
|
||||
eff.setSuppressUpdates(s);
|
||||
}
|
||||
|
|
@ -376,8 +379,9 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
|
||||
public final ReactionsLayoutInBubble reactionsLayoutInBubble = new ReactionsLayoutInBubble(this);
|
||||
public float starGiftLayoutX, starGiftLayoutY;
|
||||
public final StarGiftUniqueActionLayout starGiftLayout;
|
||||
public final WalletActionLayout walletActionLayout;
|
||||
public StarGiftUniqueActionLayout starGiftLayout;
|
||||
public WalletActionLayout walletActionLayout;
|
||||
private boolean spoilersSuppressed;
|
||||
public float walletActionLayoutX, walletActionLayoutY;
|
||||
private float walletSlidingOffset;
|
||||
|
||||
|
|
@ -545,10 +549,6 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
avatarDrawable = new AvatarDrawable();
|
||||
TAG = DownloadController.getInstance(currentAccount).generateObserverTag();
|
||||
|
||||
starGiftLayout = new StarGiftUniqueActionLayout(currentAccount, this, resourcesProvider);
|
||||
walletActionLayout = new WalletActionLayout(this, resourcesProvider);
|
||||
walletActionLayout.setOnClickListener(this::openGramTransaction);
|
||||
|
||||
giftTitlePaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16, getResources().getDisplayMetrics()));
|
||||
giftSubtitlePaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 15, getResources().getDisplayMetrics()));
|
||||
giftTextPaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 15, getResources().getDisplayMetrics()));
|
||||
|
|
@ -669,7 +669,14 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
messageObject.messageOwner.premiumEffectWasPlayed |= currentMessageObject.messageOwner.premiumEffectWasPlayed;
|
||||
}
|
||||
currentMessageObject = messageObject;
|
||||
walletActionLayout.setSurfaceEnabled(hasWalletActionLayout());
|
||||
if (hasWalletActionLayout() && walletActionLayout == null) {
|
||||
walletActionLayout = new WalletActionLayout(this, themeDelegate);
|
||||
walletActionLayout.setOnClickListener(this::openGramTransaction);
|
||||
walletActionLayout.setSpoilersSuppressed(spoilersSuppressed);
|
||||
}
|
||||
if (walletActionLayout != null) {
|
||||
walletActionLayout.setSurfaceEnabled(hasWalletActionLayout());
|
||||
}
|
||||
if (messageObject.messageOwner != null && messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGramTransfer) {
|
||||
final MessagesController messagesController = MessagesController.getInstance(currentAccount);
|
||||
final long peerDialogId = DialogObject.getPeerDialogId(messageObject.messageOwner.peer_id);
|
||||
|
|
@ -718,7 +725,16 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
birthdayLayout.detach();
|
||||
birthdayLayout = null;
|
||||
}
|
||||
starGiftLayout.set(messageObject, !messageIdChanged);
|
||||
if (starGiftLayout == null && messageObject.messageOwner != null
|
||||
&& messageObject.messageOwner.action instanceof TLRPC.TL_messageActionStarGiftUnique) {
|
||||
starGiftLayout = new StarGiftUniqueActionLayout(currentAccount, this, themeDelegate);
|
||||
if (isCellAttachedToWindow()) {
|
||||
starGiftLayout.attach();
|
||||
}
|
||||
}
|
||||
if (starGiftLayout != null) {
|
||||
starGiftLayout.set(messageObject, !messageIdChanged);
|
||||
}
|
||||
imageReceiver.setAutoRepeatCount(0);
|
||||
imageReceiver.clearDecorators();
|
||||
if (messageObject.type != MessageObject.TYPE_ACTION_WALLPAPER) {
|
||||
|
|
@ -1128,7 +1144,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
if (getPaddingTop() != topicSeparatorTopPadding) {
|
||||
setPadding(0, topicSeparatorTopPadding, 0, 0);
|
||||
}
|
||||
rippleView.setVisibility(isButtonLayout(messageObject) && !starGiftLayout.has() ? VISIBLE : GONE);
|
||||
rippleView.setVisibility(isButtonLayout(messageObject) && !hasStarGiftLayout() ? VISIBLE : GONE);
|
||||
ForumUtilities.applyTopicToMessage(messageObject);
|
||||
requestLayout();
|
||||
}
|
||||
|
|
@ -1198,7 +1214,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
rippleView.layout((int) giftButtonRect.left, (int) giftButtonRect.top, (int) giftButtonRect.right, (int) giftButtonRect.bottom);
|
||||
View diamond = walletActionLayout.getDiamondSurface();
|
||||
View diamond = walletActionLayout == null ? null : walletActionLayout.getDiamondSurface();
|
||||
if (diamond != null) diamond.layout(0, 0, dp(42), dp(42));
|
||||
}
|
||||
|
||||
|
|
@ -1224,7 +1240,9 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
avatarStoryParams.onDetachFromWindow();
|
||||
|
||||
transitionParams.onDetach();
|
||||
starGiftLayout.detach();
|
||||
if (starGiftLayout != null) {
|
||||
starGiftLayout.detach();
|
||||
}
|
||||
reactionsLayoutInBubble.onDetachFromWindow();
|
||||
if (topicSeparator != null) {
|
||||
topicSeparator.detach();
|
||||
|
|
@ -1262,7 +1280,9 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
if (currentMessageObject != null && currentMessageObject.type == MessageObject.TYPE_SUGGEST_PHOTO) {
|
||||
setMessageObject(currentMessageObject, true);
|
||||
}
|
||||
starGiftLayout.attach();
|
||||
if (starGiftLayout != null) {
|
||||
starGiftLayout.attach();
|
||||
}
|
||||
reactionsLayoutInBubble.onAttachToWindow();
|
||||
if (topicSeparator != null) {
|
||||
topicSeparator.attach();
|
||||
|
|
@ -1324,7 +1344,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
return true;
|
||||
}
|
||||
|
||||
if (starGiftLayout.has() && starGiftLayout.onTouchEvent(starGiftLayoutX, starGiftLayoutY, event)) {
|
||||
if (hasStarGiftLayout() && starGiftLayout.onTouchEvent(starGiftLayoutX, starGiftLayoutY, event)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1896,7 +1916,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
View diamond = walletActionLayout.getDiamondSurface();
|
||||
View diamond = walletActionLayout == null ? null : walletActionLayout.getDiamondSurface();
|
||||
if (diamond != null) {
|
||||
final int spec = MeasureSpec.makeMeasureSpec(dp(42), MeasureSpec.EXACTLY);
|
||||
diamond.measure(spec, spec);
|
||||
|
|
@ -1947,7 +1967,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
}
|
||||
|
||||
int exactlyHeight = 0;
|
||||
if (starGiftLayout.has()) {
|
||||
if (hasStarGiftLayout()) {
|
||||
if (!starGiftLayout.repost) {
|
||||
exactlyHeight += textY + textHeight + dp(4 + 6 + 6);
|
||||
}
|
||||
|
|
@ -2088,8 +2108,12 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
reactionsLayoutInBubble.y = getMeasuredHeight() - getPaddingTop() - reactionsLayoutInBubble.totalHeight;
|
||||
}
|
||||
|
||||
public boolean hasStarGiftLayout() {
|
||||
return starGiftLayout != null && starGiftLayout.has();
|
||||
}
|
||||
|
||||
private boolean isNewStyleButtonLayout() {
|
||||
return starGiftLayout.has()
|
||||
return hasStarGiftLayout()
|
||||
|| birthdayLayout != null
|
||||
|| currentMessageObject.type == MessageObject.TYPE_GIFT_THEME_UPDATE
|
||||
|| currentMessageObject.type == MessageObject.TYPE_COMMUNITY_CHANGED
|
||||
|
|
@ -2918,7 +2942,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
MessageObject messageObject = currentMessageObject;
|
||||
final float expanded = giftPremiumTextExpandedAnimated.set(!giftPremiumTextCollapsed);
|
||||
int imageSize = stickerSize;
|
||||
if (!starGiftLayout.has() && birthdayLayout == null && isButtonLayout(messageObject)) {
|
||||
if (!hasStarGiftLayout() && birthdayLayout == null && isButtonLayout(messageObject)) {
|
||||
stickerSize = giftRectSize - dp(106);
|
||||
if (isNewStyleButtonLayout()) {
|
||||
imageSize = getImageSize(messageObject);
|
||||
|
|
@ -2990,7 +3014,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
canvas.restore();
|
||||
}
|
||||
|
||||
if (starGiftLayout.has()) {
|
||||
if (hasStarGiftLayout()) {
|
||||
canvas.save();
|
||||
canvas.translate(starGiftLayoutX = (getWidth() - starGiftLayout.getWidth()) / 2.0f, starGiftLayoutY = starGiftLayout.repost ? dp(4) : textY + textHeight + dp(4 + 6 + 6));
|
||||
starGiftLayout.draw(canvas);
|
||||
|
|
@ -3119,7 +3143,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
canvas.restore();
|
||||
}
|
||||
|
||||
if (!starGiftLayout.has() && isButtonLayout(messageObject)) {
|
||||
if (!hasStarGiftLayout() && isButtonLayout(messageObject)) {
|
||||
canvas.save();
|
||||
float x = (previousWidth - giftRectSize) / 2f;
|
||||
if (messageObject.type != MessageObject.TYPE_ACTION_WALLPAPER) {
|
||||
|
|
@ -3713,6 +3737,8 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
x + walletActionLayout.getWidth(),
|
||||
y + walletActionLayout.getHeight()
|
||||
);
|
||||
canvas.save();
|
||||
walletActionLayout.applyCardTransform(canvas, x, y);
|
||||
canvas.drawRoundRect(walletActionRect, dp(20), dp(20), backgroundPaint);
|
||||
if (hasGradientService() && darkenBackgroundPaint.getAlpha() > 0) {
|
||||
canvas.drawRoundRect(walletActionRect, dp(20), dp(20), darkenBackgroundPaint);
|
||||
|
|
@ -3725,10 +3751,11 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
canvas.drawRoundRect(walletActionRect, dp(20), dp(20), dimPaint);
|
||||
dimPaint.setAlpha(wasAlpha);
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
MessageObject messageObject = currentMessageObject;
|
||||
if (starGiftLayout.has()) {
|
||||
if (hasStarGiftLayout()) {
|
||||
float w = starGiftLayout.getWidth() + dp(4 + 4);
|
||||
float x = (getWidth() - w) / 2f;
|
||||
float y = starGiftLayout.repost ? 0 : textY + textHeight + dp(12);
|
||||
|
|
@ -4066,7 +4093,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
|
||||
@Override
|
||||
public int getBoundsLeft() {
|
||||
if (starGiftLayout.has()) {
|
||||
if (hasStarGiftLayout()) {
|
||||
final int giftLayoutLeft = (int) (getWidth() - (starGiftLayout.getWidth() + dp(8))) / 2;
|
||||
if (starGiftLayout.repost) {
|
||||
return giftLayoutLeft;
|
||||
|
|
@ -4085,7 +4112,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
|
||||
@Override
|
||||
public int getBoundsRight() {
|
||||
if (starGiftLayout.has()) {
|
||||
if (hasStarGiftLayout()) {
|
||||
final int giftLayoutRight = (int) (getWidth() + (starGiftLayout.getWidth() + dp(8))) / 2;
|
||||
if (starGiftLayout.repost) {
|
||||
return giftLayoutRight;
|
||||
|
|
@ -4207,7 +4234,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
|
|||
AnimatedEmojiSpan.drawAnimatedEmojis(canvas, textLayout, animatedEmojiStack, 0, spoilers, 0, 0, 0, 1f, textLayout != null ? getAdaptiveEmojiColorFilter(textLayout.getPaint().getColor()) : null);
|
||||
canvas.restore();
|
||||
|
||||
if (starGiftLayout.has()) {
|
||||
if (hasStarGiftLayout()) {
|
||||
canvas.save();
|
||||
canvas.translate((getWidth() - starGiftLayout.getWidth()) / 2.0f, starGiftLayout.repost ? dp(4) : textY + textHeight + dp(4 + 6 + 6));
|
||||
starGiftLayout.drawOutbounds(canvas);
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ import androidx.annotation.Nullable;
|
|||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.ImageReceiver;
|
||||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.UserConfig;
|
||||
import org.telegram.tgnet.ConnectionsManager;
|
||||
import org.telegram.tgnet.TLRPC;
|
||||
import org.telegram.ui.ActionBar.SimpleTextView;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
|
|
@ -601,6 +603,11 @@ public class TextCell extends FrameLayout {
|
|||
public static CharSequence applyNewSpan(CharSequence str) {
|
||||
return applyNewSpan(str, false);
|
||||
}
|
||||
public static CharSequence applyNewSpanTimed(CharSequence str, int since) {
|
||||
if (ConnectionsManager.getInstance(UserConfig.selectedAccount).getCurrentTime() - since > 4 * 7 * 24 * 60 * 60)
|
||||
return str;
|
||||
return applyNewSpan(str);
|
||||
}
|
||||
public static CharSequence applyNewSpan(CharSequence str, boolean usePaintAlpha) {
|
||||
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(str);
|
||||
spannableStringBuilder.append(" d");
|
||||
|
|
|
|||
|
|
@ -4364,62 +4364,66 @@ public class ChatActivity extends BaseFragment implements
|
|||
savedChatsItem.setVisibility(getMessagesController().getSavedMessagesController().hasDialogs() ? View.VISIBLE : View.GONE);
|
||||
savedChatsGap.setVisibility(getMessagesController().getSavedMessagesController().hasDialogs() ? View.VISIBLE : View.GONE);
|
||||
} else if (chatMode != MODE_SAVED && (currentUser == null || !currentUser.self)) {
|
||||
chatNotificationsPopupWrapper = new ChatNotificationsPopupWrapper(context, currentAccount, headerItem.getPopupLayout().getSwipeBack(), false, false, new ChatNotificationsPopupWrapper.Callback() {
|
||||
@Override
|
||||
public void dismiss() {
|
||||
headerItem.toggleSubMenu();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toggleSound() {
|
||||
SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount);
|
||||
boolean enabled = !preferences.getBoolean("sound_enabled_" + NotificationsController.getSharedPrefKey(dialog_id, getTopicId()), true);
|
||||
preferences.edit().putBoolean("sound_enabled_" + NotificationsController.getSharedPrefKey(dialog_id, getTopicId()), enabled).apply();
|
||||
if (BulletinFactory.canShowBulletin(ChatActivity.this)) {
|
||||
BulletinFactory.createSoundEnabledBulletin(ChatActivity.this, enabled ? NotificationsController.SETTING_SOUND_ON : NotificationsController.SETTING_SOUND_OFF, getResourceProvider()).show();
|
||||
chatNotificationsPopupWrapper = null;
|
||||
muteItem = headerItem.lazilyAddSwipeBackItem(R.drawable.msg_mute, null, null, () -> {
|
||||
chatNotificationsPopupWrapper = new ChatNotificationsPopupWrapper(context, currentAccount, headerItem.getPopupLayout().getSwipeBack(), false, false, new ChatNotificationsPopupWrapper.Callback() {
|
||||
@Override
|
||||
public void dismiss() {
|
||||
headerItem.toggleSubMenu();
|
||||
}
|
||||
updateTitleIcons();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void muteFor(int timeInSeconds) {
|
||||
if (timeInSeconds == 0) {
|
||||
if (getMessagesController().isDialogMuted(dialog_id, getTopicId())) {
|
||||
ChatActivity.this.toggleMute(true);
|
||||
}
|
||||
@Override
|
||||
public void toggleSound() {
|
||||
SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount);
|
||||
boolean enabled = !preferences.getBoolean("sound_enabled_" + NotificationsController.getSharedPrefKey(dialog_id, getTopicId()), true);
|
||||
preferences.edit().putBoolean("sound_enabled_" + NotificationsController.getSharedPrefKey(dialog_id, getTopicId()), enabled).apply();
|
||||
if (BulletinFactory.canShowBulletin(ChatActivity.this)) {
|
||||
BulletinFactory.createMuteBulletin(ChatActivity.this, NotificationsController.SETTING_MUTE_UNMUTE, timeInSeconds, getResourceProvider()).show();
|
||||
BulletinFactory.createSoundEnabledBulletin(ChatActivity.this, enabled ? NotificationsController.SETTING_SOUND_ON : NotificationsController.SETTING_SOUND_OFF, getResourceProvider()).show();
|
||||
}
|
||||
} else {
|
||||
getNotificationsController().muteUntil(dialog_id, getTopicId(), timeInSeconds);
|
||||
if (BulletinFactory.canShowBulletin(ChatActivity.this)) {
|
||||
BulletinFactory.createMuteBulletin(ChatActivity.this, NotificationsController.SETTING_MUTE_CUSTOM, timeInSeconds, getResourceProvider()).show();
|
||||
updateTitleIcons();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void muteFor(int timeInSeconds) {
|
||||
if (timeInSeconds == 0) {
|
||||
if (getMessagesController().isDialogMuted(dialog_id, getTopicId())) {
|
||||
ChatActivity.this.toggleMute(true);
|
||||
}
|
||||
if (BulletinFactory.canShowBulletin(ChatActivity.this)) {
|
||||
BulletinFactory.createMuteBulletin(ChatActivity.this, NotificationsController.SETTING_MUTE_UNMUTE, timeInSeconds, getResourceProvider()).show();
|
||||
}
|
||||
} else {
|
||||
getNotificationsController().muteUntil(dialog_id, getTopicId(), timeInSeconds);
|
||||
if (BulletinFactory.canShowBulletin(ChatActivity.this)) {
|
||||
BulletinFactory.createMuteBulletin(ChatActivity.this, NotificationsController.SETTING_MUTE_CUSTOM, timeInSeconds, getResourceProvider()).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showCustomize() {
|
||||
if (dialog_id != 0 && chatMode != MODE_SAVED) {
|
||||
if (currentUser != null) {
|
||||
getMessagesController().putUser(currentUser, true);
|
||||
@Override
|
||||
public void showCustomize() {
|
||||
if (dialog_id != 0 && chatMode != MODE_SAVED) {
|
||||
if (currentUser != null) {
|
||||
getMessagesController().putUser(currentUser, true);
|
||||
}
|
||||
Bundle args = new Bundle();
|
||||
args.putLong("dialog_id", dialog_id);
|
||||
if (getTopicId() != 0) {
|
||||
args.putLong("topic_id", getTopicId());
|
||||
}
|
||||
presentFragment(new ProfileNotificationsActivity(args, themeDelegate));
|
||||
}
|
||||
Bundle args = new Bundle();
|
||||
args.putLong("dialog_id", dialog_id);
|
||||
if (getTopicId() != 0) {
|
||||
args.putLong("topic_id", getTopicId());
|
||||
}
|
||||
presentFragment(new ProfileNotificationsActivity(args, themeDelegate));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toggleMute() {
|
||||
ChatActivity.this.toggleMute(true);
|
||||
BulletinFactory.createMuteBulletin(ChatActivity.this, getMessagesController().isDialogMuted(dialog_id, getTopicId()), themeDelegate).show();
|
||||
}
|
||||
}, getResourceProvider());
|
||||
muteItem = headerItem.lazilyAddSwipeBackItem(R.drawable.msg_mute, null, null, chatNotificationsPopupWrapper.windowLayout);
|
||||
@Override
|
||||
public void toggleMute() {
|
||||
ChatActivity.this.toggleMute(true);
|
||||
BulletinFactory.createMuteBulletin(ChatActivity.this, getMessagesController().isDialogMuted(dialog_id, getTopicId()), themeDelegate).show();
|
||||
}
|
||||
}, getResourceProvider());
|
||||
chatNotificationsPopupWrapper.update(dialog_id, getTopicId(), null);
|
||||
return chatNotificationsPopupWrapper.windowLayout;
|
||||
});
|
||||
muteItem.setOnClickListener(view -> {
|
||||
boolean muted = MessagesController.getInstance(currentAccount).isDialogMuted(dialog_id, getTopicId());
|
||||
if (muted) {
|
||||
|
|
@ -33919,7 +33923,16 @@ public class ChatActivity extends BaseFragment implements
|
|||
break;
|
||||
}
|
||||
case OPTION_SEND_MONEY: {
|
||||
final TLRPC.User user = getMessagesController().getUser(selectedObject.getDialogId());
|
||||
if (!(selectedObject.messageOwner.action instanceof TLRPC.TL_messageActionGramTransfer)) return;
|
||||
final TLRPC.TL_messageActionGramTransfer action = (TLRPC.TL_messageActionGramTransfer) selectedObject.messageOwner.action;
|
||||
if (MessagesController.isSupportUser(currentUser)) {
|
||||
if (!TextUtils.isEmpty(action.peer_address)) {
|
||||
presentFragment(new WalletSendEnterAmount(action.peer_address));
|
||||
}
|
||||
break;
|
||||
}
|
||||
final long dialogId = selectedObject.getDialogId();
|
||||
final TLRPC.User user = getMessagesController().getUser(dialogId);
|
||||
if (user != null) {
|
||||
presentFragment(new WalletSendEnterAmount(user).setAllowOpenChat());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ import org.telegram.ui.Cells.CheckBoxCell;
|
|||
import org.telegram.ui.Stories.recorder.ButtonWithCounterView;
|
||||
import org.telegram.ui.Wallet.GramWallet;
|
||||
import org.telegram.ui.Wallet.WalletChatSendTransition;
|
||||
import org.telegram.ui.Wallet.WalletSendTransition;
|
||||
import org.telegram.ui.Wallet.WalletActivity;
|
||||
import org.telegram.ui.Wallet.WalletEngine2;
|
||||
import org.telegram.ui.Wallet.WalletSendEnterAmount;
|
||||
|
|
@ -153,6 +154,8 @@ public class ChatAttachAlertGramLayout extends ChatAttachAlert.AttachAlertLayout
|
|||
private Runnable pendingCommentAlert;
|
||||
private TL_wallet.walletTransaction queuedTransaction;
|
||||
private WalletChatSendTransition sendTransition;
|
||||
private WalletSendTransition walletSendTransition;
|
||||
private boolean sendToWallet;
|
||||
private AlertDialog commentDialog;
|
||||
|
||||
public byte[] getPublicKey() {
|
||||
|
|
@ -1152,6 +1155,12 @@ public class ChatAttachAlertGramLayout extends ChatAttachAlert.AttachAlertLayout
|
|||
return;
|
||||
}
|
||||
|
||||
final MessagesController messagesController = MessagesController.getInstance(currentAccount);
|
||||
final long neededStars = messagesController.getSendPaidMessagesStars(recipientUser.id);
|
||||
sendToWallet = messagesController.config.walletPaidMessageRecipientMessageAmountCheck.get()
|
||||
&& neededStars > 0 && amount / 1_000_000_000.0 * messagesController.config.tonUsdRate.get()
|
||||
< neededStars / 1000.0 * messagesController.starsUsdWithdrawRate1000;
|
||||
|
||||
sendButton.setLoading(true);
|
||||
amountKeyboardSuppressed = true;
|
||||
pendingKeyboardRequest = false;
|
||||
|
|
@ -1195,8 +1204,19 @@ public class ChatAttachAlertGramLayout extends ChatAttachAlert.AttachAlertLayout
|
|||
}
|
||||
|
||||
public AnimatorSet createSendTransition(Runnable completion) {
|
||||
if (destroyed || queuedTransaction == null || queuedTransaction.localMessageId == 0
|
||||
|| sendTransition != null || !amountInput.getDiamondView().canAnimateFlight()
|
||||
if (destroyed || queuedTransaction == null || sendTransition != null || walletSendTransition != null) return null;
|
||||
if (sendToWallet) {
|
||||
final WalletActivity wallet = new WalletActivity();
|
||||
wallet.setCurrentAccount(currentAccount);
|
||||
if (parentAlert.getBaseFragment() == null
|
||||
|| !parentAlert.getBaseFragment().presentFragment(wallet, false, true)) return null;
|
||||
walletSendTransition = new WalletSendTransition(parentAlert, amountInput.getDiamondView(),
|
||||
wallet, queuedTransaction, () -> {
|
||||
if (!destroyed) completion.run();
|
||||
});
|
||||
return walletSendTransition.animator();
|
||||
}
|
||||
if (queuedTransaction.localMessageId == 0 || !amountInput.getDiamondView().canAnimateFlight()
|
||||
|| !(parentAlert.getBaseFragment() instanceof ChatActivity)) return null;
|
||||
ChatActivity chat = (ChatActivity) parentAlert.getBaseFragment();
|
||||
if (chat.getCurrentAccount() != currentAccount || chat.getDialogId() != recipientUser.id
|
||||
|
|
@ -1324,9 +1344,11 @@ public class ChatAttachAlertGramLayout extends ChatAttachAlert.AttachAlertLayout
|
|||
// inlineMoreItem.bringToFront();
|
||||
amountEdit.clearFocus();
|
||||
loadFee();
|
||||
introProgress = introRevealProgress = 0f;
|
||||
introProgress = introRevealProgress = amountInput.getDiamondView().canAnimateIntro() ? 0f : 1f;
|
||||
updateIntroGeometry();
|
||||
amountInput.getDiamondView().whenReady(this::startIntroAnimation);
|
||||
if (introProgress < 1f) {
|
||||
amountInput.getDiamondView().whenReady(this::startIntroAnimation);
|
||||
}
|
||||
}
|
||||
|
||||
private void startIntroAnimation() {
|
||||
|
|
@ -1729,6 +1751,10 @@ public class ChatAttachAlertGramLayout extends ChatAttachAlert.AttachAlertLayout
|
|||
sendTransition.cancel();
|
||||
sendTransition = null;
|
||||
}
|
||||
if (walletSendTransition != null) {
|
||||
walletSendTransition.cancel();
|
||||
walletSendTransition = null;
|
||||
}
|
||||
if (feeVisibilityAnimator != null) {
|
||||
feeVisibilityAnimator.cancel();
|
||||
feeVisibilityAnimator = null;
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ import android.os.Build;
|
|||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.SystemClock;
|
||||
import android.view.Gravity;
|
||||
import android.view.HapticFeedbackConstants;
|
||||
import android.view.MotionEvent;
|
||||
|
|
@ -188,6 +189,11 @@ public class InstantCameraView extends InstantCameraViewBase implements Notifica
|
|||
private Camera2Session[] camera2Sessions = new Camera2Session[2];
|
||||
private Camera2Session camera2SessionCurrent;
|
||||
private boolean needDrawFlickerStub;
|
||||
private volatile long legacyCameraSwitchStartedNs;
|
||||
private volatile int legacyCameraSwitchSequence;
|
||||
private volatile int legacyCameraSwitchTargetSurface;
|
||||
private volatile boolean legacyCameraSwitchAwaitingFrame;
|
||||
private volatile String legacyCameraSwitchPath;
|
||||
|
||||
private boolean isCameraSessionInitiated() {
|
||||
if (useCamera2) {
|
||||
|
|
@ -791,6 +797,12 @@ public class InstantCameraView extends InstantCameraViewBase implements Notifica
|
|||
if (camera2SessionCurrent != null && camera2Sessions[isFrontface ? 1 : 0] == null) {
|
||||
bothCameras = false;
|
||||
}
|
||||
if (BuildVars.LOGS_ENABLED) {
|
||||
FileLog.d("InstantCamera legacy switch capability: dual=" + bothCameras
|
||||
+ ", initialFacing=" + (isFrontface ? "FRONT" : "BACK")
|
||||
+ ", frontSession=" + (camera2Sessions[0] != null)
|
||||
+ ", backSession=" + (camera2Sessions[1] != null));
|
||||
}
|
||||
if (camera2SessionCurrent == null) return;
|
||||
} else {
|
||||
camera2SessionCurrent = camera2Sessions[isFrontface ? 0 : 1] = Camera2Session.create(isFrontface, MessagesController.getInstance(UserConfig.selectedAccount).roundVideoSize, MessagesController.getInstance(UserConfig.selectedAccount).roundVideoSize);
|
||||
|
|
@ -1131,6 +1143,20 @@ public class InstantCameraView extends InstantCameraViewBase implements Notifica
|
|||
}
|
||||
|
||||
private void switchCamera() {
|
||||
legacyCameraSwitchStartedNs = SystemClock.elapsedRealtimeNanos();
|
||||
legacyCameraSwitchSequence++;
|
||||
legacyCameraSwitchTargetSurface = useCamera2 && bothCameras
|
||||
? 1 - surfaceIndex
|
||||
: 0;
|
||||
legacyCameraSwitchAwaitingFrame = true;
|
||||
legacyCameraSwitchPath = useCamera2
|
||||
? bothCameras ? "DUAL_PREOPENED" : "SEQUENTIAL_CAMERA2"
|
||||
: "SEQUENTIAL_CAMERA1";
|
||||
logLegacyCameraSwitchStage("requested: from="
|
||||
+ (isFrontface ? "FRONT" : "BACK")
|
||||
+ ", to=" + (isFrontface ? "BACK" : "FRONT")
|
||||
+ ", currentSurface=" + surfaceIndex
|
||||
+ ", targetSurface=" + legacyCameraSwitchTargetSurface);
|
||||
if (!(useCamera2 && bothCameras)) {
|
||||
saveLastCameraBitmap();
|
||||
if (lastBitmap != null) {
|
||||
|
|
@ -1153,7 +1179,11 @@ public class InstantCameraView extends InstantCameraViewBase implements Notifica
|
|||
camera2Sessions[isFrontface ? 1 : 0] = null;
|
||||
}
|
||||
camera2SessionCurrent = camera2Sessions[isFrontface ? 0 : 1] = Camera2Session.create(isFrontface, MessagesController.getInstance(UserConfig.selectedAccount).roundVideoSize, MessagesController.getInstance(UserConfig.selectedAccount).roundVideoSize);
|
||||
if (camera2SessionCurrent == null) return;
|
||||
if (camera2SessionCurrent == null) {
|
||||
legacyCameraSwitchAwaitingFrame = false;
|
||||
logLegacyCameraSwitchStage("failed: Camera2Session.create returned null");
|
||||
return;
|
||||
}
|
||||
camera2SessionCurrent.setRecordingVideo(true);
|
||||
previewSize[0] = new Size(camera2SessionCurrent.getPreviewWidth(), camera2SessionCurrent.getPreviewHeight());
|
||||
cameraThread.setCurrentSession(camera2SessionCurrent);
|
||||
|
|
@ -1170,6 +1200,18 @@ public class InstantCameraView extends InstantCameraViewBase implements Notifica
|
|||
cameraThread.reinitForNewCamera();
|
||||
}
|
||||
|
||||
private void logLegacyCameraSwitchStage(String stage) {
|
||||
if (!BuildVars.LOGS_ENABLED) return;
|
||||
long startedNs = legacyCameraSwitchStartedNs;
|
||||
long elapsedMs = startedNs == 0L
|
||||
? 0L
|
||||
: (SystemClock.elapsedRealtimeNanos() - startedNs) / 1_000_000L;
|
||||
FileLog.d("InstantCamera legacy switch[" + legacyCameraSwitchSequence + "] "
|
||||
+ stage + ", path=" + legacyCameraSwitchPath
|
||||
+ ", elapsedMs=" + elapsedMs
|
||||
+ ", thread=" + Thread.currentThread().getName());
|
||||
}
|
||||
|
||||
// Old Camera1 API
|
||||
@Deprecated
|
||||
private boolean initCamera() {
|
||||
|
|
@ -1331,6 +1373,10 @@ public class InstantCameraView extends InstantCameraViewBase implements Notifica
|
|||
if (BuildVars.LOGS_ENABLED) {
|
||||
FileLog.d("InstantCamera create camera session " + index);
|
||||
}
|
||||
if (legacyCameraSwitchAwaitingFrame
|
||||
&& index == legacyCameraSwitchTargetSurface) {
|
||||
logLegacyCameraSwitchStage("camera open submitted: surface=" + index);
|
||||
}
|
||||
|
||||
if (useCamera2) {
|
||||
if (bothCameras) {
|
||||
|
|
@ -1794,6 +1840,10 @@ public class InstantCameraView extends InstantCameraViewBase implements Notifica
|
|||
if (updateTexImage2) {
|
||||
cameraSurface[1].updateTexImage();
|
||||
}
|
||||
boolean completesCameraSwitch = legacyCameraSwitchAwaitingFrame
|
||||
&& surfaceIndex == legacyCameraSwitchTargetSurface
|
||||
&& (surfaceIndex == 0 && updateTexImage1
|
||||
|| surfaceIndex == 1 && updateTexImage2);
|
||||
|
||||
boolean captureFirstFrameThumb = false;
|
||||
if (!recording) {
|
||||
|
|
@ -1853,6 +1903,11 @@ public class InstantCameraView extends InstantCameraViewBase implements Notifica
|
|||
GLES20.glUseProgram(0);
|
||||
|
||||
egl10.eglSwapBuffers(eglDisplay, eglSurface);
|
||||
if (completesCameraSwitch && legacyCameraSwitchAwaitingFrame) {
|
||||
legacyCameraSwitchAwaitingFrame = false;
|
||||
logLegacyCameraSwitchStage("first target frame presented: surface="
|
||||
+ surfaceIndex);
|
||||
}
|
||||
|
||||
if (captureFirstFrameThumb) {
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
|
|
@ -1922,6 +1977,9 @@ public class InstantCameraView extends InstantCameraViewBase implements Notifica
|
|||
|
||||
cameraSurface[0] = new SurfaceTexture(cameraTexture[0]);
|
||||
cameraSurface[0].setOnFrameAvailableListener(surfaceTexture -> requestRender(true, false));
|
||||
if (legacyCameraSwitchAwaitingFrame) {
|
||||
logLegacyCameraSwitchStage("GL input recreated: surface=0");
|
||||
}
|
||||
createCamera(0, cameraSurface[0]);
|
||||
|
||||
updateScale();
|
||||
|
|
@ -1965,6 +2023,10 @@ public class InstantCameraView extends InstantCameraViewBase implements Notifica
|
|||
}
|
||||
case DO_FLIP: {
|
||||
surfaceIndex = 1 - surfaceIndex;
|
||||
if (legacyCameraSwitchAwaitingFrame) {
|
||||
logLegacyCameraSwitchStage("GL surface flip applied: surface="
|
||||
+ surfaceIndex);
|
||||
}
|
||||
|
||||
updateScale();
|
||||
|
||||
|
|
|
|||
|
|
@ -63,6 +63,9 @@ public final class InstantCameraView2 extends InstantCameraViewBase {
|
|||
private static final float ZOOM_GESTURE_EFFORT = 1.5f;
|
||||
private static final int SWITCH_PREVIEW_BITMAP_SIZE = 180;
|
||||
private static final long UI_FRAME_FALLBACK_DELAY_NS = 70_000_000L;
|
||||
private static final long CAMERA_FLIP_MINIMUM_DURATION_MS = 580L;
|
||||
private static final long CAMERA_FLIP_OUT_DURATION_MS = 120L;
|
||||
private static final long CAMERA_FLIP_MINIMUM_REVEAL_DURATION_MS = 300L;
|
||||
|
||||
private final InstantCameraView.Delegate delegate;
|
||||
private final Theme.ResourcesProvider resourcesProvider;
|
||||
|
|
@ -109,6 +112,12 @@ public final class InstantCameraView2 extends InstantCameraViewBase {
|
|||
private boolean setVisibilityFromPause;
|
||||
private boolean drawInitialPlaceholder;
|
||||
private boolean switchPlaceholderVisible;
|
||||
private boolean cameraFlipInProgress;
|
||||
private boolean cameraFlipSessionReady;
|
||||
private boolean cameraFlipFirstFrameReady;
|
||||
private boolean cameraFlipRevealStarted;
|
||||
private long cameraFlipStartedRealtimeMs;
|
||||
private int cameraFlipGeneration;
|
||||
private Bitmap lastBitmap;
|
||||
private long lastVisibleDurationMs;
|
||||
private float panTranslationY;
|
||||
|
|
@ -117,6 +126,8 @@ public final class InstantCameraView2 extends InstantCameraViewBase {
|
|||
private float zoomProgress;
|
||||
private int zoomPointerId1 = -1;
|
||||
private int zoomPointerId2 = -1;
|
||||
|
||||
private final Runnable cameraFlipRevealRunnable = this::maybeStartCameraFlipReveal;
|
||||
private boolean pinchZoomActive;
|
||||
private boolean heavyOperationsStopped;
|
||||
private float previousWindowBrightness = Float.NaN;
|
||||
|
|
@ -318,6 +329,7 @@ public final class InstantCameraView2 extends InstantCameraViewBase {
|
|||
@Override
|
||||
public void destroy(boolean async) {
|
||||
setRecordingUiFrameClockActive(false);
|
||||
cancelCameraFlipAnimation();
|
||||
if (zoomResetAnimator != null) zoomResetAnimator.cancel();
|
||||
if (session != null) {
|
||||
session.release();
|
||||
|
|
@ -681,6 +693,7 @@ public final class InstantCameraView2 extends InstantCameraViewBase {
|
|||
if (info.getState() == RoundVideoSession.State.COMPLETED
|
||||
|| info.getState() == RoundVideoSession.State.ERROR
|
||||
|| info.getState() == RoundVideoSession.State.RELEASED) {
|
||||
cancelCameraFlipAnimation();
|
||||
startHeavyOperations();
|
||||
}
|
||||
if (previous == RoundVideoSession.State.RECORDING
|
||||
|
|
@ -703,22 +716,23 @@ public final class InstantCameraView2 extends InstantCameraViewBase {
|
|||
|
||||
@Override
|
||||
public void onCameraSwitchStarted(@NonNull RoundVideoSession.CameraFacing facing) {
|
||||
showCameraSwitchPlaceholder();
|
||||
previewContainer.animate().cancel();
|
||||
previewContainer.setCameraDistance(previewContainer.getMeasuredHeight() * 8f);
|
||||
previewContainer.animate().rotationY(90f).setDuration(120L).start();
|
||||
startCameraFlipAnimation(facing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCameraSwitchCompleted(@NonNull RoundVideoSession.CameraFacing facing) {
|
||||
previewContainer.animate().cancel();
|
||||
previewContainer.setRotationY(-90f);
|
||||
previewContainer.animate().rotationY(0f).setDuration(140L).start();
|
||||
cameraFlipSessionReady = true;
|
||||
FileLog.d("RoundVideo camera flip session ready: facing=" + facing
|
||||
+ ", elapsedMs=" + getCameraFlipElapsedMs());
|
||||
maybeStartCameraFlipReveal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCameraSwitchFirstFrame() {
|
||||
hideCameraSwitchPlaceholder();
|
||||
cameraFlipFirstFrameReady = true;
|
||||
FileLog.d("RoundVideo camera flip first frame: elapsedMs="
|
||||
+ getCameraFlipElapsedMs());
|
||||
maybeStartCameraFlipReveal();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -898,7 +912,7 @@ public final class InstantCameraView2 extends InstantCameraViewBase {
|
|||
|
||||
private void switchCamera() {
|
||||
if (session == null || stateInfo == null || capabilities == null
|
||||
|| !stateInfo.canControlCamera()) {
|
||||
|| !stateInfo.canControlCamera() || cameraFlipInProgress) {
|
||||
return;
|
||||
}
|
||||
RoundVideoSession.CameraFacing facing =
|
||||
|
|
@ -944,7 +958,9 @@ public final class InstantCameraView2 extends InstantCameraViewBase {
|
|||
}
|
||||
|
||||
private void updateButtons() {
|
||||
boolean cameraControls = stateInfo != null && stateInfo.canControlCamera();
|
||||
boolean cameraControls = stateInfo != null
|
||||
&& stateInfo.canControlCamera()
|
||||
&& !cameraFlipInProgress;
|
||||
switchCameraButton.setEnabled(cameraControls);
|
||||
flashButton.setEnabled(cameraControls
|
||||
&& capabilities != null
|
||||
|
|
@ -1118,15 +1134,100 @@ public final class InstantCameraView2 extends InstantCameraViewBase {
|
|||
textureOverlayView.setAlpha(1f);
|
||||
}
|
||||
|
||||
private void startCameraFlipAnimation(
|
||||
@NonNull RoundVideoSession.CameraFacing facing
|
||||
) {
|
||||
cameraFlipGeneration++;
|
||||
removeCallbacks(cameraFlipRevealRunnable);
|
||||
cameraFlipInProgress = true;
|
||||
cameraFlipSessionReady = false;
|
||||
cameraFlipFirstFrameReady = false;
|
||||
cameraFlipRevealStarted = false;
|
||||
cameraFlipStartedRealtimeMs = SystemClock.elapsedRealtime();
|
||||
showCameraSwitchPlaceholder();
|
||||
previewContainer.animate().cancel();
|
||||
previewContainer.setRotationY(0f);
|
||||
previewContainer.setCameraDistance(previewContainer.getMeasuredHeight() * 8f);
|
||||
previewContainer.animate()
|
||||
.rotationY(90f)
|
||||
.setDuration(CAMERA_FLIP_OUT_DURATION_MS)
|
||||
.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT)
|
||||
.setListener(null)
|
||||
.start();
|
||||
FileLog.d("RoundVideo camera flip started: facing=" + facing
|
||||
+ ", minimumDurationMs=" + CAMERA_FLIP_MINIMUM_DURATION_MS);
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
private void maybeStartCameraFlipReveal() {
|
||||
if (!cameraFlipInProgress || cameraFlipRevealStarted
|
||||
|| !cameraFlipSessionReady || !cameraFlipFirstFrameReady) {
|
||||
return;
|
||||
}
|
||||
long elapsedMs = getCameraFlipElapsedMs();
|
||||
long waitMs = CAMERA_FLIP_OUT_DURATION_MS - elapsedMs;
|
||||
if (waitMs > 0L) {
|
||||
removeCallbacks(cameraFlipRevealRunnable);
|
||||
postDelayed(cameraFlipRevealRunnable, waitMs);
|
||||
return;
|
||||
}
|
||||
|
||||
cameraFlipRevealStarted = true;
|
||||
removeCallbacks(cameraFlipRevealRunnable);
|
||||
hideCameraSwitchPlaceholder();
|
||||
previewContainer.animate().cancel();
|
||||
previewContainer.setRotationY(-90f);
|
||||
long revealDurationMs = Math.max(
|
||||
CAMERA_FLIP_MINIMUM_REVEAL_DURATION_MS,
|
||||
CAMERA_FLIP_MINIMUM_DURATION_MS - elapsedMs
|
||||
);
|
||||
int generation = cameraFlipGeneration;
|
||||
FileLog.d("RoundVideo camera flip reveal started: elapsedMs=" + elapsedMs
|
||||
+ ", durationMs=" + revealDurationMs);
|
||||
previewContainer.animate()
|
||||
.rotationY(0f)
|
||||
.setDuration(revealDurationMs)
|
||||
.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT)
|
||||
.setListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
if (generation != cameraFlipGeneration) return;
|
||||
previewContainer.animate().setListener(null);
|
||||
previewContainer.setRotationY(0f);
|
||||
cameraFlipInProgress = false;
|
||||
FileLog.d("RoundVideo camera flip completed: elapsedMs="
|
||||
+ getCameraFlipElapsedMs());
|
||||
updateButtons();
|
||||
}
|
||||
})
|
||||
.start();
|
||||
}
|
||||
|
||||
private void cancelCameraFlipAnimation() {
|
||||
if (!cameraFlipInProgress && !cameraFlipRevealStarted) return;
|
||||
cameraFlipGeneration++;
|
||||
removeCallbacks(cameraFlipRevealRunnable);
|
||||
previewContainer.animate().cancel();
|
||||
previewContainer.animate().setListener(null);
|
||||
previewContainer.setRotationY(0f);
|
||||
cameraFlipInProgress = false;
|
||||
cameraFlipSessionReady = false;
|
||||
cameraFlipFirstFrameReady = false;
|
||||
cameraFlipRevealStarted = false;
|
||||
hideCameraSwitchPlaceholder();
|
||||
}
|
||||
|
||||
private long getCameraFlipElapsedMs() {
|
||||
return cameraFlipStartedRealtimeMs == 0L
|
||||
? 0L
|
||||
: Math.max(0L, SystemClock.elapsedRealtime() - cameraFlipStartedRealtimeMs);
|
||||
}
|
||||
|
||||
private void hideCameraSwitchPlaceholder() {
|
||||
if (!switchPlaceholderVisible) return;
|
||||
switchPlaceholderVisible = false;
|
||||
textureOverlayView.animate().cancel();
|
||||
textureOverlayView.animate()
|
||||
.alpha(0f)
|
||||
.setDuration(100L)
|
||||
.setInterpolator(new DecelerateInterpolator())
|
||||
.start();
|
||||
textureOverlayView.setAlpha(0f);
|
||||
}
|
||||
|
||||
private void saveLastCameraBitmap(boolean persist) {
|
||||
|
|
|
|||
|
|
@ -1045,7 +1045,7 @@ public class MessageEntityView extends EntityView {
|
|||
} else if (child instanceof ChatActionCell) {
|
||||
ChatActionCell cell = (ChatActionCell) child;
|
||||
float cleft, ctop, cright, cbottom;
|
||||
if (cell.starGiftLayout.has()) {
|
||||
if (cell.hasStarGiftLayout()) {
|
||||
cleft = container.getX() + cell.getX() + cell.getBoundsLeft();
|
||||
cright = container.getX() + cell.getX() + cell.getBoundsRight();
|
||||
ctop = container.getY() + cell.getY();
|
||||
|
|
|
|||
|
|
@ -1468,8 +1468,8 @@ public class LinkManager {
|
|||
|
||||
if (TextUtils.isEmpty(recipient)) {
|
||||
presentFragment(new WalletActivity());
|
||||
} else if (recipient.startsWith("@")) {
|
||||
final String username = recipient.substring(1);
|
||||
} else if (recipient.startsWith("@") || recipient.matches("[a-zA-Z0-9_]{1,32}")) {
|
||||
final String username = recipient.startsWith("@") ? recipient.substring(1) : recipient;
|
||||
if (TextUtils.isEmpty(username)) return true;
|
||||
final TLRPC.TL_contacts_resolveUsername req = new TLRPC.TL_contacts_resolveUsername();
|
||||
req.username = username;
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@ import org.telegram.messenger.NotificationCenter;
|
|||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.SharedConfig;
|
||||
import org.telegram.messenger.SharedPrefsHelper;
|
||||
import org.telegram.ui.Cells.TextCell;
|
||||
import org.telegram.ui.Wallet.GramWallet;
|
||||
import org.telegram.ui.Wallet.WalletActivity;
|
||||
import org.telegram.utils.settings.SharedSettings;
|
||||
|
|
@ -689,6 +690,13 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
|
|||
items.add(UItem.asShadow(null));
|
||||
}
|
||||
|
||||
final boolean walletAbove = getConnectionsManager().getCurrentTime() - 1791538462 < 4 * 7 * 24 * 60 * 60;
|
||||
if (walletAbove && getMessagesController().config.walletAvailable.get()) {
|
||||
final GramWallet wallet = GramWallet.getInstance(currentAccount);
|
||||
items.add(SettingCell.Factory.of(25, 0, 0, Theme.isCurrentThemeDark() ? R.drawable.settings_wallet_dark : R.drawable.settings_wallet, TextCell.applyNewSpanTimed(getString(R.string.WalletAttachMoney), 1790679020), null, wallet.getBalance() > 0 ? GramWallet.formatGrams(wallet.getBalance()) : null));
|
||||
items.add(UItem.asShadow(null));
|
||||
}
|
||||
|
||||
items.add(SettingCell.Factory.of(1, IconBackgroundColors.BLUE.top, IconBackgroundColors.BLUE.bottom, R.drawable.settings_account, getString(R.string.SettingsAccount), getString(R.string.SettingsAccountInfo)));
|
||||
items.add(SettingCell.Factory.of(2, IconBackgroundColors.ORANGE.top, IconBackgroundColors.ORANGE.bottom, R.drawable.settings_chat, getString(R.string.SettingsChat), getString(R.string.SettingsChatInfo)));
|
||||
items.add(SettingCell.Factory.of(3, IconBackgroundColors.GREEN.top, IconBackgroundColors.GREEN.bottom, R.drawable.settings_privacy, getString(R.string.SettingsPrivacySecurity), getString(R.string.SettingsPrivacySecurityInfo)));
|
||||
|
|
@ -700,9 +708,9 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
|
|||
items.add(SettingCell.Factory.of(10, IconBackgroundColors.PURPLE.top, IconBackgroundColors.PURPLE.bottom, R.drawable.settings_language, getString(R.string.SettingsLanguage), LocaleController.getCurrentLanguageName()));
|
||||
|
||||
items.add(UItem.asShadow(null));
|
||||
if (getMessagesController().config.walletAvailable.get()) {
|
||||
if (!walletAbove && getMessagesController().config.walletAvailable.get()) {
|
||||
final GramWallet wallet = GramWallet.getInstance(currentAccount);
|
||||
items.add(SettingCell.Factory.of(25, 0, 0, Theme.isCurrentThemeDark() ? R.drawable.settings_wallet_dark : R.drawable.settings_wallet, applyNewSpanTimed(getString(R.string.WalletAttachMoney), 1790679020), null, wallet.getBalance() > 0 ? GramWallet.formatGrams(wallet.getBalance()) : null));
|
||||
items.add(SettingCell.Factory.of(25, 0, 0, Theme.isCurrentThemeDark() ? R.drawable.settings_wallet_dark : R.drawable.settings_wallet, TextCell.applyNewSpanTimed(getString(R.string.WalletAttachMoney), 1790679020), null, wallet.getBalance() > 0 ? GramWallet.formatGrams(wallet.getBalance()) : null));
|
||||
items.add(UItem.asShadow(null));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -207,7 +207,7 @@ public class TONIntroActivity extends GradientHeaderActivity implements Notifica
|
|||
aboveTitleView.setClickable(true);
|
||||
iconTextureView = new WalletDiamondView(context, 170);
|
||||
iconTextureView.setStarParticlesView(particlesView);
|
||||
aboveTitleView.addView(iconTextureView, LayoutHelper.createFrame(170, 170, Gravity.CENTER, 0, 32, 0, 24));
|
||||
aboveTitleView.addView(iconTextureView, LayoutHelper.createFrame(170, 170, Gravity.CENTER, 0, 32, 0, 12));
|
||||
configureHeader(getString(R.string.GramEarningsTitle), AndroidUtilities.replaceArrows(AndroidUtilities.replaceSingleTag(getString(R.string.GramEarningsText), () -> {
|
||||
new ExplainStarsSheet(context).show();
|
||||
}), true), aboveTitleView, null);
|
||||
|
|
|
|||
|
|
@ -191,6 +191,7 @@ public class WalletActionLayout {
|
|||
new int[]{ 0x00FFFFFF, 0x80FFFFFF, 0x00FFFFFF },
|
||||
new float[]{ 0f, .5f, 1f }, Shader.TileMode.CLAMP));
|
||||
bounce = new ButtonBounce(parentView);
|
||||
bounce.setAdditionalInvalidate(this::invalidateCardBackground);
|
||||
}
|
||||
|
||||
public void set(boolean out, TLRPC.TL_messageActionGramTransfer action) {
|
||||
|
|
@ -379,14 +380,41 @@ public class WalletActionLayout {
|
|||
return dp(150) + (int) Math.ceil(commentText.getHeight());
|
||||
}
|
||||
|
||||
private float getCardScaleX() {
|
||||
return bounce.getScale(0.025f) * sentScale * (1f + .012f * landingPress);
|
||||
}
|
||||
|
||||
private float getCardScaleY() {
|
||||
return bounce.getScale(0.025f) * sentScale * (1f - .04f * landingPress);
|
||||
}
|
||||
|
||||
private float getCardOffsetY() {
|
||||
return dp(4) * landingPress;
|
||||
}
|
||||
|
||||
public void applyCardTransform(Canvas canvas, float x, float y) {
|
||||
canvas.translate(0, getCardOffsetY());
|
||||
canvas.scale(getCardScaleX(), getCardScaleY(), x + getWidth() / 2.0f, y + dp(70));
|
||||
}
|
||||
|
||||
private void invalidateCardBackground() {
|
||||
// ChatActionCell's gradient background is recorded in its parent's canvas.
|
||||
if (parentView.getParent() instanceof View) {
|
||||
((View) parentView.getParent()).invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private void invalidateCard() {
|
||||
parentView.invalidate();
|
||||
invalidateCardBackground();
|
||||
}
|
||||
|
||||
public void draw(Canvas canvas) {
|
||||
canvas.save();
|
||||
final float scale = bounce.getScale(0.025f) * sentScale;
|
||||
final float scaleX = scale * (1f + .012f * landingPress);
|
||||
final float scaleY = scale * (1f - .04f * landingPress);
|
||||
final float landingOffset = dp(4) * landingPress;
|
||||
canvas.translate(0, landingOffset);
|
||||
canvas.scale(scaleX, scaleY, getWidth() / 2.0f, dp(70));
|
||||
final float scaleX = getCardScaleX();
|
||||
final float scaleY = getCardScaleY();
|
||||
final float landingOffset = getCardOffsetY();
|
||||
applyCardTransform(canvas, 0, 0);
|
||||
|
||||
final float padding = dp(4);
|
||||
cardRect.set(padding, padding, getWidth() - padding, dp(140) - padding);
|
||||
|
|
@ -449,14 +477,7 @@ public class WalletActionLayout {
|
|||
gramDrawable.start();
|
||||
}
|
||||
if (!nativeDiamond && !diamondHeldForFlight) {
|
||||
canvas.save();
|
||||
if (!out && (receiveAnimator != null || spinOffset != 0f)) {
|
||||
// Keep the momentum visible on devices using the Lottie fallback.
|
||||
if (diamondSurface == null) getDiamondRestingYaw();
|
||||
canvas.rotate((float) Math.toDegrees(spinOffset), diamondBounds.exactCenterX(), diamondBounds.exactCenterY());
|
||||
}
|
||||
gramDrawable.draw(canvas);
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
if (amountText != null) {
|
||||
|
|
@ -520,7 +541,6 @@ public class WalletActionLayout {
|
|||
if (out && !diamondHeldForFlight && ribbonRevealProgress < 1f && clockReveal > 0f) {
|
||||
drawSendingClock(canvas, (1f - ribbonRevealProgress) * clockReveal);
|
||||
}
|
||||
canvas.restore();
|
||||
|
||||
if (commentText != null) {
|
||||
if ((action.comment_encrypted || action.comment_encrypted_preparing) && !preparingCommentRevealed) {
|
||||
|
|
@ -541,6 +561,7 @@ public class WalletActionLayout {
|
|||
);
|
||||
}
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
public boolean playReceiveAnimation(Runnable onEnd) {
|
||||
|
|
@ -599,7 +620,7 @@ public class WalletActionLayout {
|
|||
landingSpring.setStartVelocity(Math.max(20f, Math.min(36f, velocityDpPerSecond * .04f)));
|
||||
landingSpring.addUpdateListener((animation, value, velocity) -> {
|
||||
landingPress = value;
|
||||
parentView.invalidate();
|
||||
invalidateCard();
|
||||
});
|
||||
landingSpring.start();
|
||||
}
|
||||
|
|
@ -607,7 +628,7 @@ public class WalletActionLayout {
|
|||
private void resetLanding() {
|
||||
if (landingSpring != null) { landingSpring.cancel(); landingSpring = null; }
|
||||
landingPress = 0f;
|
||||
parentView.invalidate();
|
||||
invalidateCard();
|
||||
}
|
||||
|
||||
private void animateSentBounce() {
|
||||
|
|
@ -620,7 +641,7 @@ public class WalletActionLayout {
|
|||
sentSpring.setStartVelocity(-3f);
|
||||
sentSpring.addUpdateListener((animation, value, velocity) -> {
|
||||
sentScale = value;
|
||||
parentView.invalidate();
|
||||
invalidateCard();
|
||||
});
|
||||
sentSpring.start();
|
||||
}
|
||||
|
|
@ -628,6 +649,7 @@ public class WalletActionLayout {
|
|||
private void resetSentBounce() {
|
||||
if (sentSpring != null) { sentSpring.cancel(); sentSpring = null; }
|
||||
sentScale = 1f;
|
||||
invalidateCard();
|
||||
}
|
||||
|
||||
public void animateHighlight() {
|
||||
|
|
|
|||
|
|
@ -2483,7 +2483,7 @@ public class WalletActivity extends UniversalFragment implements NotificationCen
|
|||
if (cancelFetchFee[0] != null) cancelFetchFee[0].run();
|
||||
final Utilities.Callback2<TL_wallet.walletTransaction, String> onFee = (t, error) -> {
|
||||
cancelFetchFee[0] = null;
|
||||
if (t != null && t.fee > 0) {
|
||||
if (feeView[0] != null && t != null && t.fee > 0) {
|
||||
feeView[0].setText(formatTransactionFee(currentAccount, t.fee, resourceProvider));
|
||||
}
|
||||
};
|
||||
|
|
@ -2783,7 +2783,7 @@ public class WalletActivity extends UniversalFragment implements NotificationCen
|
|||
.setPositiveButton(LocaleController.getString(R.string.WalletOK), null)
|
||||
.show();
|
||||
});
|
||||
} else if (fee > 0 || t.nft != null || t.preview) {
|
||||
} else if (fee > 0 || t.nft != null || t.preview && !t.incoming) {
|
||||
feeView[0] = new TextView(context);
|
||||
feeView[0].setGravity(Gravity.CENTER_VERTICAL);
|
||||
feeView[0].setIncludeFontPadding(false);
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import android.graphics.Paint;
|
|||
import android.graphics.RectF;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Build;
|
||||
import android.os.PowerManager;
|
||||
import android.text.SpannableString;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
|
|
@ -61,6 +62,7 @@ public class WalletCardComponent extends FrameLayout implements NotificationCent
|
|||
private final RectF diamondDrawBounds = new RectF();
|
||||
private boolean hasBalanceDiamondTransform;
|
||||
private boolean use2D;
|
||||
private final boolean powerSaveMode;
|
||||
private float additionalTilt;
|
||||
private float gyroscopeTiltScale = 1.0f;
|
||||
private final Matrix faceProjectionMatrix = new Matrix();
|
||||
|
|
@ -104,7 +106,9 @@ public class WalletCardComponent extends FrameLayout implements NotificationCent
|
|||
int qrButtonRightPadding
|
||||
) {
|
||||
super(context);
|
||||
this.use2D = use2D;
|
||||
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
||||
powerSaveMode = powerManager != null && powerManager.isPowerSaveMode();
|
||||
this.use2D = use2D || powerSaveMode;
|
||||
this.cardIconResId = cardIconResId;
|
||||
this.qrButtonRightPadding = qrButtonRightPadding;
|
||||
setClipChildren(false);
|
||||
|
|
@ -313,6 +317,7 @@ public class WalletCardComponent extends FrameLayout implements NotificationCent
|
|||
}
|
||||
|
||||
public void setUse2D(boolean use2D) {
|
||||
use2D |= powerSaveMode;
|
||||
if (this.use2D == use2D) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import android.app.ActivityManager;
|
|||
import android.content.Context;
|
||||
import android.content.pm.ConfigurationInfo;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.os.PowerManager;
|
||||
import android.view.Choreographer;
|
||||
import android.view.Gravity;
|
||||
import android.view.MotionEvent;
|
||||
|
|
@ -90,7 +91,10 @@ public class WalletDiamondView extends FrameLayout {
|
|||
super(context);
|
||||
preferredSize = AndroidUtilities.dp(sizeDp);
|
||||
animationSizeDp = sizeDp;
|
||||
if (SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_LOW || !supportsGles3(context)) {
|
||||
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
||||
if ((powerManager != null && powerManager.isPowerSaveMode())
|
||||
|| SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_LOW
|
||||
|| !supportsGles3(context)) {
|
||||
createLottieView();
|
||||
} else if (useTextureView) {
|
||||
textureView = new GLIconTextureView(context, GLIconRenderer.DIALOG_STYLE, Icon3D.TYPE_DIAMOND) {
|
||||
|
|
@ -240,6 +244,10 @@ public class WalletDiamondView extends FrameLayout {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean canAnimateIntro() {
|
||||
return renderer != null;
|
||||
}
|
||||
|
||||
public boolean canAnimateFlight() {
|
||||
return renderer != null && isShown() && getAlpha() > .01f;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1037,6 +1037,9 @@ public class WalletSendEnterAmount extends UniversalFragment implements Notifica
|
|||
content.addView(center, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER));
|
||||
|
||||
amountInput = new AmountInputView(context, getResourceProvider(), true);
|
||||
if (!amountInput.getDiamondView().canAnimateIntro()) {
|
||||
introProgress = introRevealProgress = 1f;
|
||||
}
|
||||
center.addView(amountInput, LayoutHelper.createLinear(
|
||||
LayoutHelper.MATCH_PARENT, 64, Gravity.TOP | Gravity.CENTER_HORIZONTAL,
|
||||
16, 0, 16, 0));
|
||||
|
|
|
|||
|
|
@ -19,8 +19,10 @@ import android.widget.FrameLayout;
|
|||
|
||||
import org.telegram.tgnet.tl.TL_wallet;
|
||||
import org.telegram.ui.Components.LayoutHelper;
|
||||
import org.telegram.ui.Components.ChatAttachAlert;
|
||||
|
||||
final class WalletSendTransition {
|
||||
public final class WalletSendTransition {
|
||||
private final ChatAttachAlert sheet;
|
||||
private final ViewGroup root;
|
||||
private final View outgoing;
|
||||
private final WalletDiamondView source;
|
||||
|
|
@ -42,6 +44,17 @@ final class WalletSendTransition {
|
|||
|
||||
WalletSendTransition(ViewGroup root, View outgoing, WalletDiamondView source, WalletActivity wallet,
|
||||
TL_wallet.walletTransaction transaction, Runnable completion) {
|
||||
this(root, outgoing, source, wallet, transaction, completion, null);
|
||||
}
|
||||
|
||||
public WalletSendTransition(ChatAttachAlert sheet, WalletDiamondView source, WalletActivity wallet,
|
||||
TL_wallet.walletTransaction transaction, Runnable completion) {
|
||||
this(sheet.getContainer(), sheet.getSheetContainer(), source, wallet, transaction, completion, sheet);
|
||||
}
|
||||
|
||||
private WalletSendTransition(ViewGroup root, View outgoing, WalletDiamondView source, WalletActivity wallet,
|
||||
TL_wallet.walletTransaction transaction, Runnable completion, ChatAttachAlert sheet) {
|
||||
this.sheet = sheet;
|
||||
this.root = root;
|
||||
this.outgoing = outgoing;
|
||||
this.source = source;
|
||||
|
|
@ -53,7 +66,10 @@ final class WalletSendTransition {
|
|||
overlay = new FrameLayout(root.getContext()) {
|
||||
@Override
|
||||
protected void dispatchDraw(Canvas canvas) {
|
||||
canvas.save();
|
||||
canvas.translate(-getLeft(), -getTop());
|
||||
particles.draw(canvas);
|
||||
canvas.restore();
|
||||
super.dispatchDraw(canvas);
|
||||
if (particles.isActive()) postInvalidateOnAnimation();
|
||||
}
|
||||
|
|
@ -75,6 +91,10 @@ final class WalletSendTransition {
|
|||
flight.addUpdateListener(a -> drawFrame((float) a.getAnimatedValue()));
|
||||
animation.playTogether(flight);
|
||||
animation.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animator) {
|
||||
if (sheet != null) org.telegram.messenger.AndroidUtilities.hideKeyboard(source);
|
||||
}
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animator) { finish(); }
|
||||
@Override
|
||||
|
|
@ -84,11 +104,11 @@ final class WalletSendTransition {
|
|||
overlay.post(awaitLanding);
|
||||
}
|
||||
|
||||
AnimatorSet animator() { return animation; }
|
||||
public AnimatorSet animator() { return animation; }
|
||||
|
||||
private void awaitLanding() {
|
||||
if (finished || started) return;
|
||||
updateSourceBounds(source, outgoing, root, from);
|
||||
updateSourceBounds();
|
||||
position(from.centerX(), from.centerY(), from.width());
|
||||
TransactionCell cell = wallet.findSendLanding(transaction);
|
||||
if (cell != null && cell.getWidth() > 0) {
|
||||
|
|
@ -99,7 +119,7 @@ final class WalletSendTransition {
|
|||
}
|
||||
WalletDiamondView target = landing.getPendingDiamond();
|
||||
if (ready && target != null && target.getWidth() > 0 && !landing.isLayoutRequested()) {
|
||||
to.set(bounds(target, root));
|
||||
to.set(targetBounds(target));
|
||||
if (to.centerY() > 0 && to.centerY() < root.getHeight()) {
|
||||
started = true;
|
||||
diamond.copyRotationFrom(source);
|
||||
|
|
@ -124,12 +144,14 @@ final class WalletSendTransition {
|
|||
|
||||
private void drawFrame(float progress) {
|
||||
if (finished) return;
|
||||
updateSourceBounds(source, outgoing, root, from);
|
||||
outgoing.setTranslationY(outgoing.getHeight() * exitCurve.getInterpolation(Math.min(1f, progress * 2)));
|
||||
updateSourceBounds();
|
||||
float exitProgress = exitCurve.getInterpolation(Math.min(1f, progress * 2));
|
||||
if (sheet != null) sheet.setGramSendTransitionProgress(exitProgress);
|
||||
else outgoing.setTranslationY(outgoing.getHeight() * exitProgress);
|
||||
if (landing == null || to.isEmpty()) return;
|
||||
WalletDiamondView target = landing.getPendingDiamond();
|
||||
if (target != null && landing.matches(transaction) && target.isAttachedToWindow()) {
|
||||
to.set(bounds(target, root));
|
||||
to.set(targetBounds(target));
|
||||
}
|
||||
float q = 1f - progress;
|
||||
float controlX = from.centerX() + (to.centerX() - from.centerX()) * .35f;
|
||||
|
|
@ -141,6 +163,27 @@ final class WalletSendTransition {
|
|||
overlay.invalidate();
|
||||
}
|
||||
|
||||
private void updateSourceBounds() {
|
||||
if (sheet == null) {
|
||||
updateSourceBounds(source, outgoing, root, from);
|
||||
} else if (source.isAttachedToWindow() && source.getRootView() == root.getRootView()) {
|
||||
from.set(bounds(source, root));
|
||||
from.offset(0, sheet.currentPanTranslationY - sheet.getGramSendExitTranslationY());
|
||||
}
|
||||
}
|
||||
|
||||
private RectF targetBounds(View target) {
|
||||
if (sheet == null) return bounds(target, root);
|
||||
ViewGroup targetRoot = (ViewGroup) target.getRootView();
|
||||
RectF rect = bounds(target, targetRoot);
|
||||
int[] location = new int[2];
|
||||
targetRoot.getLocationOnScreen(location);
|
||||
rect.offset(location[0], location[1]);
|
||||
root.getLocationOnScreen(location);
|
||||
rect.offset(-location[0], -location[1]);
|
||||
return rect;
|
||||
}
|
||||
|
||||
private void position(float x, float y, float width) {
|
||||
float side = dp(60);
|
||||
diamond.setTranslationX(x - overlay.getLeft() - side / 2f);
|
||||
|
|
@ -180,7 +223,7 @@ final class WalletSendTransition {
|
|||
return rect;
|
||||
}
|
||||
|
||||
void cancel() {
|
||||
public void cancel() {
|
||||
if (finished) return;
|
||||
if (animation.isStarted()) animation.cancel();
|
||||
else finish();
|
||||
|
|
@ -205,9 +248,26 @@ final class WalletSendTransition {
|
|||
overlay.removeView(diamond);
|
||||
overlay.setClickable(false);
|
||||
source.setAlpha(sourceAlpha);
|
||||
outgoing.setTranslationY(0f);
|
||||
if (sheet == null) outgoing.setTranslationY(0f);
|
||||
else sheet.setGramSendTransitionProgress(1f);
|
||||
// Keep the last trail particles alive after the sheet window disappears.
|
||||
ViewGroup particleRoot = root;
|
||||
if (sheet != null && particles.isActive() && wallet.getParentLayout() != null) {
|
||||
ViewGroup walletRoot = wallet.getParentLayout().getView();
|
||||
if (walletRoot.isAttachedToWindow()) {
|
||||
int[] sheetLocation = new int[2];
|
||||
int[] walletLocation = new int[2];
|
||||
root.getLocationOnScreen(sheetLocation);
|
||||
walletRoot.getLocationOnScreen(walletLocation);
|
||||
root.removeView(overlay);
|
||||
overlay.setTranslationX(sheetLocation[0] - walletLocation[0]);
|
||||
overlay.setTranslationY(sheetLocation[1] - walletLocation[1]);
|
||||
walletRoot.addView(overlay, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
particleRoot = walletRoot;
|
||||
}
|
||||
}
|
||||
completion.run();
|
||||
// The last trail particles outlive the 600 ms navigation flight.
|
||||
overlay.postDelayed(() -> root.removeView(overlay), 650);
|
||||
final ViewGroup cleanupRoot = particleRoot;
|
||||
org.telegram.messenger.AndroidUtilities.runOnUIThread(() -> cleanupRoot.removeView(overlay), 650);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import androidx.core.content.ContextCompat;
|
|||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
|
||||
final class RoundVideoCameraController {
|
||||
|
||||
|
|
@ -78,6 +79,46 @@ final class RoundVideoCameraController {
|
|||
}
|
||||
}
|
||||
|
||||
private static final class CameraSelection {
|
||||
final String id;
|
||||
final RoundVideoSession.CameraFacing facing;
|
||||
final CameraCharacteristics characteristics;
|
||||
final Size previewSize;
|
||||
final Size recordingSize;
|
||||
final int sourceCropSize;
|
||||
final RoundVideoSession.CameraResolution cameraResolution;
|
||||
final RoundVideoSession.FrameRate frameRate;
|
||||
final Range<Integer> fpsRange;
|
||||
final OutputPair regularFallbackPair;
|
||||
final float maximumZoomRatio;
|
||||
|
||||
CameraSelection(
|
||||
String id,
|
||||
RoundVideoSession.CameraFacing facing,
|
||||
CameraCharacteristics characteristics,
|
||||
Size previewSize,
|
||||
Size recordingSize,
|
||||
int sourceCropSize,
|
||||
RoundVideoSession.CameraResolution cameraResolution,
|
||||
RoundVideoSession.FrameRate frameRate,
|
||||
Range<Integer> fpsRange,
|
||||
OutputPair regularFallbackPair,
|
||||
float maximumZoomRatio
|
||||
) {
|
||||
this.id = id;
|
||||
this.facing = facing;
|
||||
this.characteristics = characteristics;
|
||||
this.previewSize = previewSize;
|
||||
this.recordingSize = recordingSize;
|
||||
this.sourceCropSize = sourceCropSize;
|
||||
this.cameraResolution = cameraResolution;
|
||||
this.frameRate = frameRate;
|
||||
this.fpsRange = fpsRange;
|
||||
this.regularFallbackPair = regularFallbackPair;
|
||||
this.maximumZoomRatio = maximumZoomRatio;
|
||||
}
|
||||
}
|
||||
|
||||
private static final int PREVIEW_SHORT_SIDE = 720;
|
||||
private static final int MAXIMUM_SOURCE_SHORT_SIDE = 1088;
|
||||
private static final int MAXIMUM_SOURCE_LONG_SIDE = 1920;
|
||||
|
|
@ -148,6 +189,19 @@ final class RoundVideoCameraController {
|
|||
private boolean frameRateFallbackAttempted;
|
||||
private boolean frameRatePolicyResolved;
|
||||
private boolean force30Fps;
|
||||
private CameraSelection frontSelection;
|
||||
private CameraSelection backSelection;
|
||||
private boolean warmSwitchSupported;
|
||||
private boolean warmSwitchDisabled;
|
||||
private boolean warmCameraOpening;
|
||||
private CameraDevice warmCameraDevice;
|
||||
private CameraDevice closingStandbyDevice;
|
||||
private CameraSelection warmCameraSelection;
|
||||
private RoundVideoSession.CameraFacing pendingWarmSwitchFacing;
|
||||
private long warmCameraOpenRequestedNs;
|
||||
private long cameraCloseRequestedNs;
|
||||
private long switchSelectionStartedNs;
|
||||
private boolean lastSwitchUsedWarmDevice;
|
||||
private long segmentStartedNs;
|
||||
private long cameraOpenRequestedNs;
|
||||
private long captureSessionRequestedNs;
|
||||
|
|
@ -373,7 +427,9 @@ final class RoundVideoCameraController {
|
|||
public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surfaceTexture) {
|
||||
if (awaitingSwitchPreviewFrame) {
|
||||
awaitingSwitchPreviewFrame = false;
|
||||
diagnostics.log("camera switch first preview frame");
|
||||
diagnostics.log("camera switch first preview frame: path="
|
||||
+ (lastSwitchUsedWarmDevice ? "WARM_DEVICE" : "SEQUENTIAL")
|
||||
+ ", totalElapsedMs=" + elapsedMs(cameraSwitchStartedNs));
|
||||
callback.onCameraSwitchFirstFrame();
|
||||
}
|
||||
long now = SystemClock.elapsedRealtimeNanos();
|
||||
|
|
@ -431,7 +487,12 @@ final class RoundVideoCameraController {
|
|||
return;
|
||||
}
|
||||
try {
|
||||
switchSelectionStartedNs = SystemClock.elapsedRealtimeNanos();
|
||||
selectCameraAndSizes(requestedFacing);
|
||||
long selectionElapsedMs = elapsedMs(switchSelectionStartedNs);
|
||||
if (cameraDevice == null && recorder == null) {
|
||||
prepareWarmSwitchSupport();
|
||||
}
|
||||
SurfaceTexture previewTexture = previewView.getSurfaceTexture();
|
||||
if (previewTexture == null) return;
|
||||
previewTexture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
|
||||
|
|
@ -446,12 +507,15 @@ final class RoundVideoCameraController {
|
|||
);
|
||||
recordingSurface = glProcessor.getCameraSurface();
|
||||
}
|
||||
openInitialWarmCameraIfNeeded();
|
||||
opening = true;
|
||||
cameraOpenRequestedNs = SystemClock.elapsedRealtimeNanos();
|
||||
diagnostics.log("camera open requested: id=" + cameraId
|
||||
+ ", preview=" + previewSize
|
||||
+ ", recording=" + recordingSize
|
||||
+ ", crop=" + sourceCropSize);
|
||||
+ ", crop=" + sourceCropSize
|
||||
+ ", selectionElapsedMs=" + selectionElapsedMs
|
||||
+ ", warmSwitch=" + warmSwitchSupported);
|
||||
cameraManager.openCamera(cameraId, deviceCallback, cameraHandler);
|
||||
} catch (Exception e) {
|
||||
opening = false;
|
||||
|
|
@ -498,12 +562,34 @@ final class RoundVideoCameraController {
|
|||
zoomProgress = 0f;
|
||||
callback.onCameraSwitchStarted(facing);
|
||||
cameraSwitchStartedNs = SystemClock.elapsedRealtimeNanos();
|
||||
lastSwitchUsedWarmDevice = false;
|
||||
diagnostics.log("camera device switch started: from=" + activeFacing + ", to=" + facing);
|
||||
if (glProcessor != null) glProcessor.beginCameraSwitch(activeFacing, facing);
|
||||
if (switchToWarmCamera(facing)) {
|
||||
return;
|
||||
}
|
||||
if (warmCameraOpening
|
||||
&& warmCameraSelection != null
|
||||
&& warmCameraSelection.facing == facing) {
|
||||
pendingWarmSwitchFacing = facing;
|
||||
diagnostics.log("camera switch path: waiting for warm device open");
|
||||
return;
|
||||
}
|
||||
continueSequentialSwitch();
|
||||
}
|
||||
|
||||
private void continueSequentialSwitch() {
|
||||
pendingWarmSwitchFacing = null;
|
||||
lastSwitchUsedWarmDevice = false;
|
||||
diagnostics.log("camera switch path: sequential"
|
||||
+ (warmSwitchSupported
|
||||
? ", reason=warm device not ready"
|
||||
: ", reason=concurrent pair unavailable"));
|
||||
closeCaptureSession();
|
||||
if (cameraDevice != null) {
|
||||
CameraDevice device = cameraDevice;
|
||||
cameraDevice = null;
|
||||
cameraCloseRequestedNs = SystemClock.elapsedRealtimeNanos();
|
||||
device.close();
|
||||
} else if (!opening) {
|
||||
switchingCamera = false;
|
||||
|
|
@ -516,19 +602,32 @@ final class RoundVideoCameraController {
|
|||
public void onOpened(@NonNull CameraDevice device) {
|
||||
opening = false;
|
||||
diagnostics.log("camera opened: id=" + device.getId()
|
||||
+ ", elapsedMs=" + elapsedMs(cameraOpenRequestedNs));
|
||||
+ ", elapsedMs=" + elapsedMs(cameraOpenRequestedNs)
|
||||
+ (notifySwitchCompletion ? ", switchElapsedMs="
|
||||
+ elapsedMs(cameraSwitchStartedNs) : ""));
|
||||
if (!active || switchingCamera) {
|
||||
device.close();
|
||||
return;
|
||||
}
|
||||
cameraDevice = device;
|
||||
createCaptureSession();
|
||||
if (warmSwitchSupported && warmCameraOpening) {
|
||||
diagnostics.log("active camera opened; waiting for warm camera before session");
|
||||
} else {
|
||||
createCaptureSession();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisconnected(@NonNull CameraDevice device) {
|
||||
opening = false;
|
||||
diagnostics.log("camera disconnected: id=" + device.getId());
|
||||
if (device == warmCameraDevice) {
|
||||
warmCameraDevice = null;
|
||||
closingStandbyDevice = device;
|
||||
device.close();
|
||||
disableWarmSwitch("standby device disconnected", null);
|
||||
return;
|
||||
}
|
||||
boolean unexpected = active
|
||||
&& !stopping
|
||||
&& !switchingCamera
|
||||
|
|
@ -546,6 +645,14 @@ final class RoundVideoCameraController {
|
|||
@Override
|
||||
public void onError(@NonNull CameraDevice device, int error) {
|
||||
opening = false;
|
||||
if (device == warmCameraDevice) {
|
||||
warmCameraDevice = null;
|
||||
closingStandbyDevice = device;
|
||||
device.close();
|
||||
disableWarmSwitch("standby device error=" + cameraErrorName(error)
|
||||
+ " (" + error + ")", null);
|
||||
return;
|
||||
}
|
||||
if (cameraDevice == device) {
|
||||
closeCaptureSession();
|
||||
cameraDevice = null;
|
||||
|
|
@ -557,7 +664,20 @@ final class RoundVideoCameraController {
|
|||
|
||||
@Override
|
||||
public void onClosed(@NonNull CameraDevice device) {
|
||||
if (device == closingStandbyDevice) {
|
||||
closingStandbyDevice = null;
|
||||
diagnostics.log("standby camera closed: id=" + device.getId());
|
||||
return;
|
||||
}
|
||||
if (device == warmCameraDevice) {
|
||||
warmCameraDevice = null;
|
||||
diagnostics.log("standby camera closed: id=" + device.getId());
|
||||
return;
|
||||
}
|
||||
if (switchingCamera) {
|
||||
diagnostics.log("camera closed for sequential switch: elapsedMs="
|
||||
+ elapsedMs(cameraCloseRequestedNs)
|
||||
+ ", switchElapsedMs=" + elapsedMs(cameraSwitchStartedNs));
|
||||
switchingCamera = false;
|
||||
if (active) openCameraIfReady();
|
||||
} else if (reopenAfterCameraClose) {
|
||||
|
|
@ -567,6 +687,174 @@ final class RoundVideoCameraController {
|
|||
}
|
||||
};
|
||||
|
||||
private final CameraDevice.StateCallback warmDeviceCallback =
|
||||
new CameraDevice.StateCallback() {
|
||||
@Override
|
||||
public void onOpened(@NonNull CameraDevice device) {
|
||||
warmCameraOpening = false;
|
||||
if (!active || stopping || warmSwitchDisabled
|
||||
|| warmCameraSelection == null
|
||||
|| !device.getId().equals(warmCameraSelection.id)) {
|
||||
diagnostics.log("stale warm camera open ignored: id=" + device.getId());
|
||||
device.close();
|
||||
return;
|
||||
}
|
||||
warmCameraDevice = device;
|
||||
diagnostics.log("warm camera opened: id=" + device.getId()
|
||||
+ ", facing=" + warmCameraSelection.facing
|
||||
+ ", elapsedMs=" + elapsedMs(warmCameraOpenRequestedNs));
|
||||
if (cameraDevice != null && captureSession == null
|
||||
&& !switchingCamera) {
|
||||
diagnostics.log("both camera devices opened; configuring active session");
|
||||
createCaptureSession();
|
||||
}
|
||||
RoundVideoSession.CameraFacing pending = pendingWarmSwitchFacing;
|
||||
if (pending != null && pending == warmCameraSelection.facing) {
|
||||
pendingWarmSwitchFacing = null;
|
||||
if (!switchToWarmCamera(pending)) {
|
||||
continueSequentialSwitch();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisconnected(@NonNull CameraDevice device) {
|
||||
handleWarmDeviceFailure(device, "disconnected", null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(@NonNull CameraDevice device, int error) {
|
||||
handleWarmDeviceFailure(
|
||||
device,
|
||||
"error=" + cameraErrorName(error) + " (" + error + ")",
|
||||
new IllegalStateException("Warm camera device error: "
|
||||
+ cameraErrorName(error) + " (" + error + ")")
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClosed(@NonNull CameraDevice device) {
|
||||
if (device == closingStandbyDevice) {
|
||||
closingStandbyDevice = null;
|
||||
diagnostics.log("standby camera closed: id=" + device.getId());
|
||||
return;
|
||||
}
|
||||
if (device == warmCameraDevice) {
|
||||
warmCameraDevice = null;
|
||||
diagnostics.log("standby camera closed: id=" + device.getId());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private void openInitialWarmCameraIfNeeded() {
|
||||
if (!warmSwitchSupported || warmSwitchDisabled
|
||||
|| warmCameraOpening || warmCameraDevice != null) {
|
||||
return;
|
||||
}
|
||||
CameraSelection selection = selectionForFacing(
|
||||
selectedFacing == RoundVideoSession.CameraFacing.FRONT
|
||||
? RoundVideoSession.CameraFacing.BACK
|
||||
: RoundVideoSession.CameraFacing.FRONT
|
||||
);
|
||||
requestWarmCameraOpen(selection);
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
private void requestWarmCameraOpen(@Nullable CameraSelection selection) {
|
||||
if (selection == null || warmCameraOpening || warmCameraDevice != null) return;
|
||||
try {
|
||||
warmCameraSelection = selection;
|
||||
warmCameraOpening = true;
|
||||
warmCameraOpenRequestedNs = SystemClock.elapsedRealtimeNanos();
|
||||
diagnostics.log("warm camera open requested: id=" + selection.id
|
||||
+ ", facing=" + selection.facing);
|
||||
cameraManager.openCamera(selection.id, warmDeviceCallback, cameraHandler);
|
||||
} catch (Exception e) {
|
||||
warmCameraOpening = false;
|
||||
disableWarmSwitch("open request failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean switchToWarmCamera(@NonNull RoundVideoSession.CameraFacing facing) {
|
||||
CameraDevice targetDevice = warmCameraDevice;
|
||||
CameraSelection targetSelection = warmCameraSelection;
|
||||
if (targetDevice == null || targetSelection == null
|
||||
|| targetSelection.facing != facing) {
|
||||
return false;
|
||||
}
|
||||
SurfaceTexture previewTexture = previewView.getSurfaceTexture();
|
||||
if (previewTexture == null) {
|
||||
disableWarmSwitch("preview SurfaceTexture unavailable", null);
|
||||
return false;
|
||||
}
|
||||
|
||||
CameraDevice previousDevice = cameraDevice;
|
||||
CameraSelection previousSelection = activeFacing == null
|
||||
? null
|
||||
: selectionForFacing(activeFacing);
|
||||
closeCaptureSession();
|
||||
warmCameraDevice = previousDevice;
|
||||
warmCameraSelection = previousSelection;
|
||||
cameraDevice = targetDevice;
|
||||
applySelection(targetSelection);
|
||||
previewTexture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
|
||||
if (glProcessor != null) {
|
||||
glProcessor.updateInputConfiguration(
|
||||
recordingSize,
|
||||
sourceCropSize,
|
||||
isCameraTimestampRealtime()
|
||||
);
|
||||
recordingSurface = glProcessor.getCameraSurface();
|
||||
}
|
||||
lastSwitchUsedWarmDevice = true;
|
||||
diagnostics.log("camera switch path: warm device, targetId=" + cameraId
|
||||
+ ", standbyId=" + (previousDevice == null
|
||||
? "none" : previousDevice.getId())
|
||||
+ ", preparationMs=" + elapsedMs(cameraSwitchStartedNs));
|
||||
createCaptureSession();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void handleWarmDeviceFailure(
|
||||
@NonNull CameraDevice device,
|
||||
@NonNull String reason,
|
||||
@Nullable Exception activeError
|
||||
) {
|
||||
boolean promoted = device == cameraDevice;
|
||||
if (device == warmCameraDevice) warmCameraDevice = null;
|
||||
warmCameraOpening = false;
|
||||
device.close();
|
||||
if (promoted) {
|
||||
closeCaptureSession();
|
||||
cameraDevice = null;
|
||||
if (activeError != null) reportError(activeError);
|
||||
else reportError(new IllegalStateException("Active warm camera " + reason));
|
||||
return;
|
||||
}
|
||||
disableWarmSwitch("standby device " + reason, activeError);
|
||||
if (pendingWarmSwitchFacing != null) {
|
||||
continueSequentialSwitch();
|
||||
} else if (active && cameraDevice != null && captureSession == null
|
||||
&& !switchingCamera) {
|
||||
diagnostics.log("warm camera failed during startup; configuring active camera only");
|
||||
createCaptureSession();
|
||||
}
|
||||
}
|
||||
|
||||
private void disableWarmSwitch(@NonNull String reason, @Nullable Exception error) {
|
||||
warmSwitchDisabled = true;
|
||||
warmSwitchSupported = false;
|
||||
diagnostics.log("camera warm-switch disabled: reason=" + reason
|
||||
+ (error == null ? "" : ", error=" + error));
|
||||
CameraDevice warm = warmCameraDevice;
|
||||
warmCameraDevice = null;
|
||||
warmCameraSelection = null;
|
||||
if (warm != null && warm != cameraDevice) {
|
||||
closingStandbyDevice = warm;
|
||||
warm.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void createCaptureSession() {
|
||||
CameraDevice device = cameraDevice;
|
||||
if (device == null || previewSurface == null || recordingSurface == null) return;
|
||||
|
|
@ -581,7 +869,13 @@ final class RoundVideoCameraController {
|
|||
cameraHandler
|
||||
);
|
||||
} catch (CameraAccessException | IllegalArgumentException e) {
|
||||
if (activeFrameRate == RoundVideoSession.FrameRate.FPS_60) {
|
||||
if (warmCameraDevice != null && !warmSwitchDisabled) {
|
||||
diagnostics.log("camera session request failed with warm device open; "
|
||||
+ "retrying with standby device closed: " + e);
|
||||
if (switchingCamera) lastSwitchUsedWarmDevice = false;
|
||||
disableWarmSwitch("session request failed", e);
|
||||
createCaptureSession();
|
||||
} else if (activeFrameRate == RoundVideoSession.FrameRate.FPS_60) {
|
||||
fallbackTo30Fps("60 fps session creation rejected", e);
|
||||
} else {
|
||||
reportError(e);
|
||||
|
|
@ -593,7 +887,10 @@ final class RoundVideoCameraController {
|
|||
new CameraCaptureSession.StateCallback() {
|
||||
@Override
|
||||
public void onConfigured(@NonNull CameraCaptureSession session) {
|
||||
if (!active || cameraDevice == null) {
|
||||
if (!active || cameraDevice == null
|
||||
|| session.getDevice() != cameraDevice) {
|
||||
diagnostics.log("stale capture session ignored: deviceId="
|
||||
+ session.getDevice().getId());
|
||||
session.close();
|
||||
return;
|
||||
}
|
||||
|
|
@ -604,14 +901,16 @@ final class RoundVideoCameraController {
|
|||
if (glProcessor != null) glProcessor.onCameraSessionConfigured();
|
||||
boolean wasSwitch = notifySwitchCompletion;
|
||||
notifySwitchCompletion = false;
|
||||
if (wasSwitch) switchingCamera = false;
|
||||
awaitingSwitchPreviewFrame = wasSwitch;
|
||||
submitRepeatingRequest();
|
||||
diagnostics.log("capture session configured: facing=" + activeFacing
|
||||
+ ", fpsRange=" + activeFpsRange
|
||||
+ ", elapsedMs=" + elapsedMs(captureSessionRequestedNs)
|
||||
+ ", segmentElapsedMs=" + elapsedMs(segmentStartedNs)
|
||||
+ (wasSwitch ? ", switchElapsedMs="
|
||||
+ elapsedMs(cameraSwitchStartedNs) : ""));
|
||||
+ (wasSwitch ? ", switchPath="
|
||||
+ (lastSwitchUsedWarmDevice ? "WARM_DEVICE" : "SEQUENTIAL")
|
||||
+ ", switchElapsedMs=" + elapsedMs(cameraSwitchStartedNs) : ""));
|
||||
previewView.post(RoundVideoCameraController.this::updatePreviewTransform);
|
||||
callback.onConfigured(
|
||||
new CameraInfo(
|
||||
|
|
@ -638,14 +937,28 @@ final class RoundVideoCameraController {
|
|||
@Override
|
||||
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
|
||||
session.close();
|
||||
if (cameraDevice == null || session.getDevice() != cameraDevice) {
|
||||
diagnostics.log("stale capture session configuration failure ignored: id="
|
||||
+ session.getDevice().getId());
|
||||
return;
|
||||
}
|
||||
if (captureSession == session) {
|
||||
captureSession = null;
|
||||
repeatingBuilder = null;
|
||||
}
|
||||
if (!active || cameraDevice == null || switchingCamera || stopping) {
|
||||
if (!active || cameraDevice == null || stopping) {
|
||||
diagnostics.log("stale capture session configuration failure ignored");
|
||||
return;
|
||||
}
|
||||
if (warmCameraDevice != null && !warmSwitchDisabled) {
|
||||
diagnostics.log("camera session configuration failed with warm device "
|
||||
+ "open; "
|
||||
+ "retrying with standby device closed");
|
||||
if (switchingCamera) lastSwitchUsedWarmDevice = false;
|
||||
disableWarmSwitch("session configuration failed", null);
|
||||
createCaptureSession();
|
||||
return;
|
||||
}
|
||||
if (activeFrameRate == RoundVideoSession.FrameRate.FPS_60) {
|
||||
fallbackTo30Fps("60 fps session configuration failed", null);
|
||||
} else {
|
||||
|
|
@ -1022,6 +1335,16 @@ final class RoundVideoCameraController {
|
|||
|
||||
private void selectCameraAndSizes(@NonNull RoundVideoSession.CameraFacing facing)
|
||||
throws CameraAccessException {
|
||||
CameraSelection cached = selectionForFacing(facing);
|
||||
if (cached != null) {
|
||||
applySelection(cached);
|
||||
diagnostics.log("camera outputs restored from cache: id=" + cached.id
|
||||
+ ", facing=" + facing
|
||||
+ ", preview=" + cached.previewSize
|
||||
+ ", recording=" + cached.recordingSize
|
||||
+ ", fps=" + cached.frameRate.getValue());
|
||||
return;
|
||||
}
|
||||
resolveSessionFrameRatePolicy();
|
||||
int requiredFacing = facing == RoundVideoSession.CameraFacing.FRONT
|
||||
? CameraCharacteristics.LENS_FACING_FRONT
|
||||
|
|
@ -1142,6 +1465,96 @@ final class RoundVideoCameraController {
|
|||
+ (activeFrameRate != requestedFrameRate
|
||||
? " (fallback from " + requestedFrameRate.getValue() + ")" : ""));
|
||||
logCameraConfigurationOnce(facing, selectedId, selectedCharacteristics, sizes);
|
||||
cacheSelection(captureSelection());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private CameraSelection selectionForFacing(@NonNull RoundVideoSession.CameraFacing facing) {
|
||||
return facing == RoundVideoSession.CameraFacing.FRONT
|
||||
? frontSelection
|
||||
: backSelection;
|
||||
}
|
||||
|
||||
private void cacheSelection(@NonNull CameraSelection selection) {
|
||||
if (selection.facing == RoundVideoSession.CameraFacing.FRONT) {
|
||||
frontSelection = selection;
|
||||
} else {
|
||||
backSelection = selection;
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private CameraSelection captureSelection() {
|
||||
return new CameraSelection(
|
||||
cameraId,
|
||||
selectedFacing,
|
||||
characteristics,
|
||||
previewSize,
|
||||
recordingSize,
|
||||
sourceCropSize,
|
||||
activeCameraResolution,
|
||||
activeFrameRate,
|
||||
activeFpsRange,
|
||||
regularFallbackPair,
|
||||
maximumZoomRatio
|
||||
);
|
||||
}
|
||||
|
||||
private void applySelection(@NonNull CameraSelection selection) {
|
||||
cameraId = selection.id;
|
||||
selectedFacing = selection.facing;
|
||||
characteristics = selection.characteristics;
|
||||
previewSize = selection.previewSize;
|
||||
recordingSize = selection.recordingSize;
|
||||
sourceCropSize = selection.sourceCropSize;
|
||||
activeCameraResolution = selection.cameraResolution;
|
||||
activeFrameRate = selection.frameRate;
|
||||
activeFpsRange = selection.fpsRange;
|
||||
regularFallbackPair = selection.regularFallbackPair;
|
||||
maximumZoomRatio = selection.maximumZoomRatio;
|
||||
frameRateFallbackAttempted = false;
|
||||
resetCaptureFpsMeasurement();
|
||||
}
|
||||
|
||||
private void prepareWarmSwitchSupport() {
|
||||
if (warmSwitchDisabled || warmSwitchSupported) {
|
||||
return;
|
||||
}
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
|
||||
warmSwitchDisabled = true;
|
||||
diagnostics.log("camera warm-switch capability: supported=false, reason=API<30");
|
||||
return;
|
||||
}
|
||||
CameraSelection initial = captureSelection();
|
||||
RoundVideoSession.CameraFacing otherFacing = initial.facing
|
||||
== RoundVideoSession.CameraFacing.FRONT
|
||||
? RoundVideoSession.CameraFacing.BACK
|
||||
: RoundVideoSession.CameraFacing.FRONT;
|
||||
try {
|
||||
selectCameraAndSizes(otherFacing);
|
||||
CameraSelection other = captureSelection();
|
||||
warmSwitchSupported = isConcurrentPair(initial.id, other.id);
|
||||
if (!warmSwitchSupported) warmSwitchDisabled = true;
|
||||
diagnostics.log("camera warm-switch capability: supported="
|
||||
+ warmSwitchSupported
|
||||
+ ", pair=" + initial.id + "+" + other.id
|
||||
+ (warmSwitchSupported ? "" : ", reason=pair not advertised"));
|
||||
} catch (Exception e) {
|
||||
warmSwitchDisabled = true;
|
||||
diagnostics.log("camera warm-switch capability unavailable: " + e);
|
||||
} finally {
|
||||
applySelection(initial);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isConcurrentPair(@NonNull String first, @NonNull String second)
|
||||
throws CameraAccessException {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) return false;
|
||||
Set<Set<String>> concurrentSets = cameraManager.getConcurrentCameraIds();
|
||||
for (Set<String> ids : concurrentSets) {
|
||||
if (ids.contains(first) && ids.contains(second)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void resolveSessionFrameRatePolicy() throws CameraAccessException {
|
||||
|
|
@ -1365,6 +1778,9 @@ final class RoundVideoCameraController {
|
|||
recordingSize = pair.recording;
|
||||
sourceCropSize = pair.cropSize;
|
||||
activeCameraResolution = pair.cameraResolution;
|
||||
frontSelection = null;
|
||||
backSelection = null;
|
||||
disableWarmSwitch("frame-rate fallback changed stream configuration", error);
|
||||
SurfaceTexture previewTexture = previewView.getSurfaceTexture();
|
||||
if (previewTexture != null) {
|
||||
previewTexture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
|
||||
|
|
@ -1506,11 +1922,20 @@ final class RoundVideoCameraController {
|
|||
awaitingSwitchPreviewFrame = false;
|
||||
repeatingBuilder = null;
|
||||
torchVerificationPending = false;
|
||||
pendingWarmSwitchFacing = null;
|
||||
warmCameraOpening = false;
|
||||
closeCaptureSession();
|
||||
if (cameraDevice != null) {
|
||||
cameraDevice.close();
|
||||
cameraDevice = null;
|
||||
}
|
||||
CameraDevice warm = warmCameraDevice;
|
||||
warmCameraDevice = null;
|
||||
warmCameraSelection = null;
|
||||
if (warm != null) warm.close();
|
||||
CameraDevice closingStandby = closingStandbyDevice;
|
||||
closingStandbyDevice = null;
|
||||
if (closingStandby != null && closingStandby != warm) closingStandby.close();
|
||||
if (previewSurface != null) {
|
||||
previewSurface.release();
|
||||
previewSurface = null;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@ import org.telegram.tgnet.SerializedData;
|
|||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
|
@ -84,6 +87,14 @@ public class Localization {
|
|||
public Builder addLocalization(HashMap<String, String> localization) {
|
||||
if (localizations == null) {
|
||||
localizations = new SparseArray<>(localization.size());
|
||||
// SparseArray.put shifts existing entries for out-of-order keys.
|
||||
// A stable sort also preserves the last value for colliding hashes.
|
||||
final ArrayList<Map.Entry<String, String>> entries = new ArrayList<>(localization.entrySet());
|
||||
Collections.sort(entries, Comparator.comparingInt(a -> a.getKey().hashCode()));
|
||||
for (Map.Entry<String, String> entry : entries) {
|
||||
localizations.append(entry.getKey().hashCode(), entry.getValue());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
for (Map.Entry<String, String> entry : localization.entrySet()) {
|
||||
localizations.put(entry.getKey().hashCode(), entry.getValue());
|
||||
|
|
|
|||
|
|
@ -10069,7 +10069,7 @@
|
|||
<string name="MyTON">My TON</string>
|
||||
<string name="GramEarnings">Gram Earnings</string>
|
||||
<string name="GramEarningsTitle">Gram Earnings</string>
|
||||
<string name="GramEarningsText">Your Gram from gifts,\nads and Fragment</string>
|
||||
<string name="GramEarningsText">Your Gram from gifts,\nads and Fragment.</string>
|
||||
<string name="GramEarningsHint">You can withdraw your Grams using Fragment.</string>
|
||||
<string name="TodoMenuHint">You are viewing actions for one task.\nYou can switch to actions for the list.</string>
|
||||
<string name="PollMenuHint">You are viewing actions for one option.\nYou can switch to actions for the poll.</string>
|
||||
|
|
|
|||
|
|
@ -129,22 +129,6 @@ android {
|
|||
}
|
||||
buildConfigField "boolean", "BUNDLE", "true"
|
||||
}
|
||||
bundleAfat_SDK23 {
|
||||
ndk {
|
||||
abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
|
||||
}
|
||||
sourceSets.debug {
|
||||
manifest.srcFile '../TMessagesProj/config/debug/AndroidManifest_SDK23.xml'
|
||||
}
|
||||
sourceSets.release {
|
||||
manifest.srcFile '../TMessagesProj/config/release/AndroidManifest_SDK23.xml'
|
||||
}
|
||||
minSdkVersion 23
|
||||
ext {
|
||||
abiVersionCode = 2
|
||||
}
|
||||
buildConfigField "boolean", "BUNDLE", "true"
|
||||
}
|
||||
afat {
|
||||
ndk {
|
||||
abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
|
||||
|
|
|
|||
|
|
@ -137,15 +137,6 @@ android {
|
|||
abiVersionCode = 1
|
||||
}
|
||||
}
|
||||
bundleAfat_SDK23 {
|
||||
ndk {
|
||||
abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
|
||||
}
|
||||
minSdkVersion 23
|
||||
ext {
|
||||
abiVersionCode = 2
|
||||
}
|
||||
}
|
||||
afat {
|
||||
ndk {
|
||||
abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ org.telegram.tgnet.TLRPC.TL_folders_deleteFolder #1c295881
|
|||
org.telegram.tgnet.TLRPC.TL_forumTopic_layer147 #5920d6dc
|
||||
org.telegram.tgnet.TLRPC.TL_help_premiumPromo_layer140 #e0360f1b
|
||||
org.telegram.tgnet.TLRPC.TL_inputMessagesFilterPhotoVideoDocuments #d95e73bb
|
||||
org.telegram.tgnet.TLRPC.TL_messageActionChatJoinedViaCommunity #4a8bfe80
|
||||
org.telegram.tgnet.TLRPC.TL_messageActionCreatedBroadcastList #55555557
|
||||
org.telegram.tgnet.TLRPC.TL_messageActionLoginUnknownLocation #555555f5
|
||||
org.telegram.tgnet.TLRPC.TL_messageActionPhoneNumberRequest #01baa035
|
||||
|
|
@ -42,6 +41,7 @@ org.telegram.tgnet.TLRPC.TL_peerNotifySettingsEmpty_layer77 #70a68512
|
|||
org.telegram.tgnet.TLRPC.TL_poll_toDelete #af746786
|
||||
org.telegram.tgnet.TLRPC.TL_premiumGiftOption #79c059f7
|
||||
org.telegram.tgnet.TLRPC.TL_replyInlineMarkup_layer228_old #58f7fcb6
|
||||
org.telegram.tgnet.TLRPC.TL_userFull #7fe738c4
|
||||
org.telegram.tgnet.TLRPC.TL_userStatusHidden #cf7d64b1
|
||||
org.telegram.tgnet.TLRPC.TL_user_layer185 #4fe9cce0
|
||||
org.telegram.tgnet.TLRPC.TL_videoEncrypted #55555553
|
||||
|
|
@ -58,4 +58,5 @@ org.telegram.tgnet.tl.TL_stories.TL_mediaAreaWeather2 #855f223e
|
|||
org.telegram.tgnet.tl.TL_stories.TL_mediaAreaWeatherOld #4386f849
|
||||
org.telegram.tgnet.tl.TL_update.TL_updateBotSubscriptionExpire #a8ae3eb1
|
||||
org.telegram.tgnet.tl.TL_update.TL_updateTranscribeAudio #88617090
|
||||
org.telegram.tgnet.tl.TL_wallet.mnemonic_decryptedKeyPart #8b90dd08
|
||||
org.telegram.tgnet.tl.legacy.TL_legacy_message.TL_message_layer118 #f52e6b7f
|
||||
|
|
@ -11,8 +11,25 @@ public sealed class TlGen_BotVerification : TlGen_Object {
|
|||
public data class TL_botVerification(
|
||||
public val bot_id: Long,
|
||||
public val icon: Long,
|
||||
public val description: String,
|
||||
public val description: TlGen_TextWithEntities,
|
||||
) : TlGen_BotVerification() {
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt64(bot_id)
|
||||
stream.writeInt64(icon)
|
||||
description.serializeToStream(stream)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0xF72E0ED9U
|
||||
}
|
||||
}
|
||||
|
||||
public data class TL_botVerification_layer229(
|
||||
public val bot_id: Long,
|
||||
public val icon: Long,
|
||||
public val description: String,
|
||||
) : TlGen_Object {
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt64(bot_id)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ public sealed class TlGen_BotVerifierSettings : TlGen_Object {
|
|||
public val can_modify_custom_description: Boolean,
|
||||
public val icon: Long,
|
||||
public val company: String,
|
||||
public val custom_description: String?,
|
||||
public val custom_description: TlGen_TextWithEntities?,
|
||||
) : TlGen_BotVerifierSettings() {
|
||||
internal val flags: UInt
|
||||
get() {
|
||||
|
|
@ -23,6 +23,33 @@ public sealed class TlGen_BotVerifierSettings : TlGen_Object {
|
|||
return result
|
||||
}
|
||||
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt32(flags.toInt())
|
||||
stream.writeInt64(icon)
|
||||
stream.writeString(company)
|
||||
custom_description?.serializeToStream(stream)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0xA12AEFFFU
|
||||
}
|
||||
}
|
||||
|
||||
public data class TL_botVerifierSettings_layer229(
|
||||
public val can_modify_custom_description: Boolean,
|
||||
public val icon: Long,
|
||||
public val company: String,
|
||||
public val custom_description: String?,
|
||||
) : TlGen_Object {
|
||||
internal val flags: UInt
|
||||
get() {
|
||||
var result = 0U
|
||||
if (custom_description != null) result = result or 1U
|
||||
if (can_modify_custom_description) result = result or 2U
|
||||
return result
|
||||
}
|
||||
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt32(flags.toInt())
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.Double
|
||||
import kotlin.String
|
||||
import kotlin.UInt
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_CurrencyRate : TlGen_Object {
|
||||
public data class TL_currencyRate(
|
||||
public val currency: String,
|
||||
public val rate: Double,
|
||||
) : TlGen_CurrencyRate() {
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeString(currency)
|
||||
stream.writeDouble(rate)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x30D9743CU
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.Byte
|
||||
import kotlin.Long
|
||||
import kotlin.UInt
|
||||
import kotlin.collections.List
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_InputTonConnectOauthSession : TlGen_Object {
|
||||
public data class TL_inputTonConnectOauthSession(
|
||||
public val session_id: Long,
|
||||
public val challenge_answer: List<Byte>,
|
||||
public val body: List<Byte>,
|
||||
public val proof: TlGen_WalletOwnershipProof,
|
||||
) : TlGen_InputTonConnectOauthSession() {
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt64(session_id)
|
||||
stream.writeByteArray(challenge_answer.toByteArray())
|
||||
stream.writeByteArray(body.toByteArray())
|
||||
proof.serializeToStream(stream)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x629F66CEU
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.Byte
|
||||
import kotlin.UInt
|
||||
import kotlin.collections.List
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_InputWalletReplacement : TlGen_Object {
|
||||
public data object TL_inputWalletNew : TlGen_InputWalletReplacement() {
|
||||
public const val MAGIC: UInt = 0x63A440DCU
|
||||
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
}
|
||||
}
|
||||
|
||||
public data class TL_inputWalletImported(
|
||||
public val public_key: List<Byte>,
|
||||
public val anchor_public_key: List<Byte>?,
|
||||
public val proof: TlGen_WalletOwnershipProof,
|
||||
) : TlGen_InputWalletReplacement() {
|
||||
internal val flags: UInt
|
||||
get() {
|
||||
var result = 0U
|
||||
if (anchor_public_key != null) result = result or 1U
|
||||
return result
|
||||
}
|
||||
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt32(flags.toInt())
|
||||
stream.writeByteArray(public_key.toByteArray())
|
||||
anchor_public_key?.let { stream.writeByteArray(it.toByteArray()) }
|
||||
proof.serializeToStream(stream)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x66A66A3BU
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1365,6 +1365,83 @@ public sealed class TlGen_MessageAction : TlGen_Object {
|
|||
}
|
||||
}
|
||||
|
||||
public data class TL_messageActionChatJoinedViaCommunity(
|
||||
public val community_id: Long,
|
||||
) : TlGen_MessageAction() {
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt64(community_id)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x4A8BFE80U
|
||||
}
|
||||
}
|
||||
|
||||
public data class TL_messageActionGramTransfer(
|
||||
public val comment_encrypted: Boolean,
|
||||
public val amount: Long,
|
||||
public val peer_address: String,
|
||||
public val transaction_id: String,
|
||||
public val comment: String?,
|
||||
) : TlGen_MessageAction() {
|
||||
internal val flags: UInt
|
||||
get() {
|
||||
var result = 0U
|
||||
if (comment != null) result = result or 1U
|
||||
if (comment_encrypted) result = result or 2U
|
||||
return result
|
||||
}
|
||||
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt32(flags.toInt())
|
||||
stream.writeInt64(amount)
|
||||
stream.writeString(peer_address)
|
||||
stream.writeString(transaction_id)
|
||||
comment?.let { stream.writeString(it) }
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x9329EA33U
|
||||
}
|
||||
}
|
||||
|
||||
public data class TL_messageActionWalletTonConnectRequest(
|
||||
public val accepted: Boolean,
|
||||
public val declined: Boolean,
|
||||
public val session_id: Long,
|
||||
public val expires: Int,
|
||||
public val topic: String?,
|
||||
public val trace_id: String?,
|
||||
public val dapp_name: String?,
|
||||
) : TlGen_MessageAction() {
|
||||
internal val flags: UInt
|
||||
get() {
|
||||
var result = 0U
|
||||
if (topic != null) result = result or 1U
|
||||
if (trace_id != null) result = result or 2U
|
||||
if (accepted) result = result or 4U
|
||||
if (declined) result = result or 8U
|
||||
if (dapp_name != null) result = result or 16U
|
||||
return result
|
||||
}
|
||||
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt32(flags.toInt())
|
||||
stream.writeInt64(session_id)
|
||||
stream.writeInt32(expires)
|
||||
topic?.let { stream.writeString(it) }
|
||||
trace_id?.let { stream.writeString(it) }
|
||||
dapp_name?.let { stream.writeString(it) }
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x69B8C4BFU
|
||||
}
|
||||
}
|
||||
|
||||
public data class TL_messageActionChatCreate_layer132(
|
||||
public val title: String,
|
||||
public val users: List<Int>,
|
||||
|
|
|
|||
|
|
@ -427,6 +427,21 @@ public sealed class TlGen_MessageEntity : TlGen_Object {
|
|||
}
|
||||
}
|
||||
|
||||
public data class TL_messageEntityTonAddress(
|
||||
public val offset: Int,
|
||||
public val length: Int,
|
||||
) : TlGen_MessageEntity() {
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt32(offset)
|
||||
stream.writeInt32(length)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0xFDABBFCDU
|
||||
}
|
||||
}
|
||||
|
||||
public data class TL_messageEntityMentionName_layer132(
|
||||
public val offset: Int,
|
||||
public val length: Int,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.Boolean
|
||||
import kotlin.String
|
||||
import kotlin.UInt
|
||||
import kotlin.collections.List
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_OnrampAvailability : TlGen_Object {
|
||||
public data class TL_onrampAvailability(
|
||||
public val allowed: Boolean,
|
||||
public val buy_allowed: Boolean,
|
||||
public val country_code: String,
|
||||
public val state: String?,
|
||||
public val methods: List<TlGen_OnrampMethodAvailability>,
|
||||
) : TlGen_OnrampAvailability() {
|
||||
internal val flags: UInt
|
||||
get() {
|
||||
var result = 0U
|
||||
if (allowed) result = result or 1U
|
||||
if (buy_allowed) result = result or 2U
|
||||
if (state != null) result = result or 4U
|
||||
return result
|
||||
}
|
||||
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt32(flags.toInt())
|
||||
stream.writeString(country_code)
|
||||
state?.let { stream.writeString(it) }
|
||||
TlGen_Vector.serialize(stream, methods)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0xF9C84973U
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.String
|
||||
import kotlin.UInt
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_OnrampLimits : TlGen_Object {
|
||||
public data class TL_onrampLimits(
|
||||
public val base_currency: String,
|
||||
public val base_min_amount: String,
|
||||
public val base_max_amount: String,
|
||||
public val crypto_min_amount: String,
|
||||
public val crypto_max_amount: String,
|
||||
public val payment_method: String,
|
||||
) : TlGen_OnrampLimits() {
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeString(base_currency)
|
||||
stream.writeString(base_min_amount)
|
||||
stream.writeString(base_max_amount)
|
||||
stream.writeString(crypto_min_amount)
|
||||
stream.writeString(crypto_max_amount)
|
||||
stream.writeString(payment_method)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x7BE2677EU
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.Boolean
|
||||
import kotlin.String
|
||||
import kotlin.UInt
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_OnrampMethodAvailability : TlGen_Object {
|
||||
public data class TL_onrampMethodAvailability(
|
||||
public val available: Boolean,
|
||||
public val payment_method: String,
|
||||
) : TlGen_OnrampMethodAvailability() {
|
||||
internal val flags: UInt
|
||||
get() {
|
||||
var result = 0U
|
||||
if (available) result = result or 1U
|
||||
return result
|
||||
}
|
||||
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt32(flags.toInt())
|
||||
stream.writeString(payment_method)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x9EC8C6A8U
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.Boolean
|
||||
import kotlin.String
|
||||
import kotlin.UInt
|
||||
import kotlin.collections.List
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_OnrampProviderInfo : TlGen_Object {
|
||||
public data class TL_onrampProviderInfo(
|
||||
public val supports_base_currencies: Boolean,
|
||||
public val supports_limits: Boolean,
|
||||
public val supports_quote: Boolean,
|
||||
public val id: String,
|
||||
public val name: String,
|
||||
public val crypto_currencies: List<String>,
|
||||
) : TlGen_OnrampProviderInfo() {
|
||||
internal val flags: UInt
|
||||
get() {
|
||||
var result = 0U
|
||||
if (supports_base_currencies) result = result or 1U
|
||||
if (supports_limits) result = result or 2U
|
||||
if (supports_quote) result = result or 4U
|
||||
return result
|
||||
}
|
||||
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt32(flags.toInt())
|
||||
stream.writeString(id)
|
||||
stream.writeString(name)
|
||||
TlGen_Vector.serializeString(stream, crypto_currencies)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x0DC27582U
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.Int
|
||||
import kotlin.String
|
||||
import kotlin.UInt
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_OnrampQuote : TlGen_Object {
|
||||
public data class TL_onrampQuote(
|
||||
public val base_currency: String,
|
||||
public val base_amount: String,
|
||||
public val crypto_currency: String,
|
||||
public val crypto_amount: String,
|
||||
public val crypto_price: String,
|
||||
public val fee_amount: String,
|
||||
public val extra_fee_amount: String,
|
||||
public val network_fee_amount: String,
|
||||
public val total_amount: String,
|
||||
public val payment_method: String,
|
||||
public val expires_date: Int,
|
||||
) : TlGen_OnrampQuote() {
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeString(base_currency)
|
||||
stream.writeString(base_amount)
|
||||
stream.writeString(crypto_currency)
|
||||
stream.writeString(crypto_amount)
|
||||
stream.writeString(crypto_price)
|
||||
stream.writeString(fee_amount)
|
||||
stream.writeString(extra_fee_amount)
|
||||
stream.writeString(network_fee_amount)
|
||||
stream.writeString(total_amount)
|
||||
stream.writeString(payment_method)
|
||||
stream.writeInt32(expires_date)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x7A8011E9U
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.Int
|
||||
import kotlin.String
|
||||
import kotlin.UInt
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_OnrampSession : TlGen_Object {
|
||||
public data class TL_onrampSession(
|
||||
public val provider: String,
|
||||
public val session_id: String,
|
||||
public val url: String,
|
||||
public val expires_date: Int,
|
||||
) : TlGen_OnrampSession() {
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeString(provider)
|
||||
stream.writeString(session_id)
|
||||
stream.writeString(url)
|
||||
stream.writeInt32(expires_date)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0xD1E42E24U
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -461,4 +461,17 @@ public sealed class TlGen_RichText : TlGen_Object {
|
|||
public const val MAGIC: UInt = 0xAFC79CD6U
|
||||
}
|
||||
}
|
||||
|
||||
public data class TL_textTonAddress(
|
||||
public val text: TlGen_RichText,
|
||||
) : TlGen_RichText() {
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
text.serializeToStream(stream)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x3CD2A36AU
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.String
|
||||
import kotlin.UInt
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_TonConnectManifest : TlGen_Object {
|
||||
public data class TL_tonConnectManifest(
|
||||
public val url: String,
|
||||
public val name: String,
|
||||
public val icon: TlGen_WebDocument?,
|
||||
) : TlGen_TonConnectManifest() {
|
||||
internal val flags: UInt
|
||||
get() {
|
||||
var result = 0U
|
||||
if (icon != null) result = result or 1U
|
||||
return result
|
||||
}
|
||||
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt32(flags.toInt())
|
||||
stream.writeString(url)
|
||||
stream.writeString(name)
|
||||
icon?.serializeToStream(stream)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x12229264U
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.Long
|
||||
import kotlin.UInt
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_TonConnectNextEventId : TlGen_Object {
|
||||
public data class TL_tonConnectNextEventId(
|
||||
public val event_id: Long,
|
||||
) : TlGen_TonConnectNextEventId() {
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt64(event_id)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x582464E3U
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.Byte
|
||||
import kotlin.Int
|
||||
import kotlin.Long
|
||||
import kotlin.String
|
||||
import kotlin.UInt
|
||||
import kotlin.collections.List
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_TonConnectRequest : TlGen_Object {
|
||||
public data class TL_tonConnectRequest(
|
||||
public val session_id: Long,
|
||||
public val msg_id: Int,
|
||||
public val body: List<Byte>,
|
||||
public val expires: Int,
|
||||
public val topic: String?,
|
||||
public val trace_id: String?,
|
||||
) : TlGen_TonConnectRequest() {
|
||||
internal val flags: UInt
|
||||
get() {
|
||||
var result = 0U
|
||||
if (topic != null) result = result or 1U
|
||||
if (trace_id != null) result = result or 2U
|
||||
return result
|
||||
}
|
||||
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt32(flags.toInt())
|
||||
stream.writeInt64(session_id)
|
||||
stream.writeInt32(msg_id)
|
||||
stream.writeByteArray(body.toByteArray())
|
||||
stream.writeInt32(expires)
|
||||
topic?.let { stream.writeString(it) }
|
||||
trace_id?.let { stream.writeString(it) }
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0xA15F8513U
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.Boolean
|
||||
import kotlin.Byte
|
||||
import kotlin.Int
|
||||
import kotlin.Long
|
||||
import kotlin.String
|
||||
import kotlin.UInt
|
||||
import kotlin.collections.List
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_TonConnectSession : TlGen_Object {
|
||||
public data class TL_tonConnectSession(
|
||||
public val pending: Boolean,
|
||||
public val closing: Boolean,
|
||||
public val closed: Boolean,
|
||||
public val id: Long,
|
||||
public val dapp_client_id: String,
|
||||
public val client_id: String?,
|
||||
public val nonce: List<Byte>,
|
||||
public val manifest: TlGen_TonConnectManifest?,
|
||||
public val manifest_error: Int?,
|
||||
public val date: Int,
|
||||
) : TlGen_TonConnectSession() {
|
||||
internal val flags: UInt
|
||||
get() {
|
||||
var result = 0U
|
||||
if (pending) result = result or 1U
|
||||
if (closing) result = result or 2U
|
||||
if (closed) result = result or 4U
|
||||
if (client_id != null) result = result or 8U
|
||||
if (manifest != null) result = result or 16U
|
||||
if (manifest_error != null) result = result or 32U
|
||||
return result
|
||||
}
|
||||
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt32(flags.toInt())
|
||||
stream.writeInt64(id)
|
||||
stream.writeString(dapp_client_id)
|
||||
client_id?.let { stream.writeString(it) }
|
||||
stream.writeByteArray(nonce.toByteArray())
|
||||
manifest?.serializeToStream(stream)
|
||||
manifest_error?.let { stream.writeInt32(it) }
|
||||
stream.writeInt32(date)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x126556C6U
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2518,4 +2518,96 @@ public sealed class TlGen_Update : TlGen_Object {
|
|||
public const val MAGIC: UInt = 0x7C1079D6U
|
||||
}
|
||||
}
|
||||
|
||||
public data class TL_updateWalletState(
|
||||
public val state: TlGen_WalletState,
|
||||
) : TlGen_Update() {
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
state.serializeToStream(stream)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x6AC3F2AAU
|
||||
}
|
||||
}
|
||||
|
||||
public data class TL_updateSentWalletTransaction(
|
||||
public val gasless: Boolean,
|
||||
public val msg_hash: String,
|
||||
public val transaction: TlGen_WalletTransaction?,
|
||||
) : TlGen_Update() {
|
||||
internal val flags: UInt
|
||||
get() {
|
||||
var result = 0U
|
||||
if (gasless) result = result or 1U
|
||||
if (transaction != null) result = result or 2U
|
||||
return result
|
||||
}
|
||||
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt32(flags.toInt())
|
||||
stream.writeString(msg_hash)
|
||||
transaction?.serializeToStream(stream)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0xB1434D4AU
|
||||
}
|
||||
}
|
||||
|
||||
public data class TL_updateWalletGaslessInfo(
|
||||
public val available: Boolean,
|
||||
public val left: Int,
|
||||
public val reset_at: Int,
|
||||
public val min_amount: Long,
|
||||
public val relayer_address: String,
|
||||
) : TlGen_Update() {
|
||||
internal val flags: UInt
|
||||
get() {
|
||||
var result = 0U
|
||||
if (available) result = result or 1U
|
||||
return result
|
||||
}
|
||||
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt32(flags.toInt())
|
||||
stream.writeInt32(left)
|
||||
stream.writeInt32(reset_at)
|
||||
stream.writeInt64(min_amount)
|
||||
stream.writeString(relayer_address)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0xA8AE1CACU
|
||||
}
|
||||
}
|
||||
|
||||
public data class TL_updateWalletTonConnectSession(
|
||||
public val session: TlGen_TonConnectSession,
|
||||
) : TlGen_Update() {
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
session.serializeToStream(stream)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x50A38E0EU
|
||||
}
|
||||
}
|
||||
|
||||
public data class TL_updateWalletTonConnectPendingDisconnect(
|
||||
public val session_ids: List<Long>,
|
||||
) : TlGen_Update() {
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
TlGen_Vector.serializeLong(stream, session_ids)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0xD1EE8199U
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,11 +44,14 @@ public sealed class TlGen_UrlAuthResult : TlGen_Object {
|
|||
public val request_phone_number: Boolean,
|
||||
public val match_codes_first: Boolean,
|
||||
public val is_app: Boolean,
|
||||
public val request_wallet: Boolean,
|
||||
public val bot: TlGen_User,
|
||||
public val domain: String,
|
||||
public val match_codes: List<String>?,
|
||||
public val user_id_hint: Long?,
|
||||
public val verified_app_name: String?,
|
||||
public val tc_session_id: Long?,
|
||||
public val tc_client_id: String?,
|
||||
public val multiflags_2: Multiflags_2?,
|
||||
) : TlGen_UrlAuthResult() {
|
||||
internal val flags: UInt
|
||||
|
|
@ -62,6 +65,9 @@ public sealed class TlGen_UrlAuthResult : TlGen_Object {
|
|||
if (match_codes_first) result = result or 32U
|
||||
if (is_app) result = result or 64U
|
||||
if (verified_app_name != null) result = result or 128U
|
||||
if (request_wallet) result = result or 256U
|
||||
if (tc_session_id != null) result = result or 512U
|
||||
if (tc_client_id != null) result = result or 1024U
|
||||
return result
|
||||
}
|
||||
|
||||
|
|
@ -77,6 +83,8 @@ public sealed class TlGen_UrlAuthResult : TlGen_Object {
|
|||
match_codes?.let { TlGen_Vector.serializeString(stream, it) }
|
||||
user_id_hint?.let { stream.writeInt64(it) }
|
||||
verified_app_name?.let { stream.writeString(it) }
|
||||
tc_session_id?.let { stream.writeInt64(it) }
|
||||
tc_client_id?.let { stream.writeString(it) }
|
||||
}
|
||||
|
||||
public data class Multiflags_2(
|
||||
|
|
@ -87,7 +95,7 @@ public sealed class TlGen_UrlAuthResult : TlGen_Object {
|
|||
)
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x3CD623ECU
|
||||
public const val MAGIC: UInt = 0xBDCA6167U
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ public sealed class TlGen_Username : TlGen_Object {
|
|||
public data class TL_username(
|
||||
public val editable: Boolean,
|
||||
public val active: Boolean,
|
||||
public val deletable: Boolean,
|
||||
public val expired: Boolean,
|
||||
public val username: String,
|
||||
) : TlGen_Username() {
|
||||
internal val flags: UInt
|
||||
|
|
@ -18,6 +20,8 @@ public sealed class TlGen_Username : TlGen_Object {
|
|||
var result = 0U
|
||||
if (editable) result = result or 1U
|
||||
if (active) result = result or 2U
|
||||
if (deletable) result = result or 4U
|
||||
if (expired) result = result or 8U
|
||||
return result
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.Byte
|
||||
import kotlin.Int
|
||||
import kotlin.UInt
|
||||
import kotlin.collections.List
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_WalletOwnershipProof : TlGen_Object {
|
||||
public data class TL_walletOwnershipProof(
|
||||
public val timestamp: Int,
|
||||
public val signature: List<Byte>,
|
||||
) : TlGen_WalletOwnershipProof() {
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt32(timestamp)
|
||||
stream.writeByteArray(signature.toByteArray())
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x60BCCB0DU
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.Boolean
|
||||
import kotlin.Byte
|
||||
import kotlin.Long
|
||||
import kotlin.String
|
||||
import kotlin.UInt
|
||||
import kotlin.collections.List
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_WalletState : TlGen_Object {
|
||||
public data class TL_walletStateEmpty(
|
||||
public val creating: Boolean,
|
||||
) : TlGen_WalletState() {
|
||||
internal val flags: UInt
|
||||
get() {
|
||||
var result = 0U
|
||||
if (creating) result = result or 1U
|
||||
return result
|
||||
}
|
||||
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt32(flags.toInt())
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x9CB9B2ECU
|
||||
}
|
||||
}
|
||||
|
||||
public data class TL_walletState(
|
||||
public val backup_enabled: Boolean,
|
||||
public val can_export_phrase: Boolean,
|
||||
public val can_enable_backup: Boolean,
|
||||
public val address: String,
|
||||
public val public_key: List<Byte>,
|
||||
public val balance: Long,
|
||||
) : TlGen_WalletState() {
|
||||
internal val flags: UInt
|
||||
get() {
|
||||
var result = 0U
|
||||
if (backup_enabled) result = result or 1U
|
||||
if (can_export_phrase) result = result or 2U
|
||||
if (can_enable_backup) result = result or 4U
|
||||
return result
|
||||
}
|
||||
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt32(flags.toInt())
|
||||
stream.writeString(address)
|
||||
stream.writeByteArray(public_key.toByteArray())
|
||||
stream.writeInt64(balance)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x95C5346BU
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.Boolean
|
||||
import kotlin.Int
|
||||
import kotlin.Long
|
||||
import kotlin.String
|
||||
import kotlin.UInt
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_WalletTransaction : TlGen_Object {
|
||||
public data class TL_walletTransaction(
|
||||
public val incoming: Boolean,
|
||||
public val gasless: Boolean,
|
||||
public val failed: Boolean,
|
||||
public val key_change: Boolean,
|
||||
public val comment_encrypted: Boolean,
|
||||
public val id: String,
|
||||
public val amount: Long,
|
||||
public val fee: Long,
|
||||
public val date: Int,
|
||||
public val peer: TlGen_WalletTransactionPeer,
|
||||
public val comment: String?,
|
||||
public val tx_hash: String?,
|
||||
public val nft: TlGen_wallet_NftItem?,
|
||||
) : TlGen_WalletTransaction() {
|
||||
internal val flags: UInt
|
||||
get() {
|
||||
var result = 0U
|
||||
if (incoming) result = result or 1U
|
||||
if (gasless) result = result or 2U
|
||||
if (failed) result = result or 4U
|
||||
if (comment != null) result = result or 8U
|
||||
if (tx_hash != null) result = result or 16U
|
||||
if (key_change) result = result or 32U
|
||||
if (comment_encrypted) result = result or 64U
|
||||
if (nft != null) result = result or 128U
|
||||
return result
|
||||
}
|
||||
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt32(flags.toInt())
|
||||
stream.writeString(id)
|
||||
stream.writeInt64(amount)
|
||||
stream.writeInt64(fee)
|
||||
stream.writeInt32(date)
|
||||
peer.serializeToStream(stream)
|
||||
comment?.let { stream.writeString(it) }
|
||||
tx_hash?.let { stream.writeString(it) }
|
||||
nft?.serializeToStream(stream)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x952DC143U
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.Long
|
||||
import kotlin.String
|
||||
import kotlin.UInt
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_WalletTransactionPeer : TlGen_Object {
|
||||
public data class TL_walletTransactionPeerUser(
|
||||
public val user_id: Long,
|
||||
public val address: String,
|
||||
public val domain: String?,
|
||||
) : TlGen_WalletTransactionPeer() {
|
||||
internal val flags: UInt
|
||||
get() {
|
||||
var result = 0U
|
||||
if (domain != null) result = result or 1U
|
||||
return result
|
||||
}
|
||||
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt32(flags.toInt())
|
||||
stream.writeInt64(user_id)
|
||||
stream.writeString(address)
|
||||
domain?.let { stream.writeString(it) }
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0xD4EA706DU
|
||||
}
|
||||
}
|
||||
|
||||
public data class TL_walletTransactionPeerAddress(
|
||||
public val address: String,
|
||||
public val domain: String?,
|
||||
) : TlGen_WalletTransactionPeer() {
|
||||
internal val flags: UInt
|
||||
get() {
|
||||
var result = 0U
|
||||
if (domain != null) result = result or 1U
|
||||
return result
|
||||
}
|
||||
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt32(flags.toInt())
|
||||
stream.writeString(address)
|
||||
domain?.let { stream.writeString(it) }
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x062CC1BCU
|
||||
}
|
||||
}
|
||||
|
||||
public data class TL_walletTransactionPeerOnramp(
|
||||
public val address: String,
|
||||
public val domain: String?,
|
||||
public val provider_name: String,
|
||||
) : TlGen_WalletTransactionPeer() {
|
||||
internal val flags: UInt
|
||||
get() {
|
||||
var result = 0U
|
||||
if (domain != null) result = result or 1U
|
||||
return result
|
||||
}
|
||||
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt32(flags.toInt())
|
||||
stream.writeString(address)
|
||||
domain?.let { stream.writeString(it) }
|
||||
stream.writeString(provider_name)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0xE595186EU
|
||||
}
|
||||
}
|
||||
|
||||
public data object TL_walletTransactionPeerUnsupported : TlGen_WalletTransactionPeer() {
|
||||
public const val MAGIC: UInt = 0x728BED5AU
|
||||
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.Byte
|
||||
import kotlin.Long
|
||||
import kotlin.String
|
||||
import kotlin.UInt
|
||||
import kotlin.collections.List
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_WalletUserAddress : TlGen_Object {
|
||||
public data class TL_walletUserAddress(
|
||||
public val user_id: Long?,
|
||||
public val address: String,
|
||||
public val public_key: List<Byte>,
|
||||
) : TlGen_WalletUserAddress() {
|
||||
internal val flags: UInt
|
||||
get() {
|
||||
var result = 0U
|
||||
if (user_id != null) result = result or 1U
|
||||
return result
|
||||
}
|
||||
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt32(flags.toInt())
|
||||
user_id?.let { stream.writeInt64(it) }
|
||||
stream.writeString(address)
|
||||
stream.writeByteArray(public_key.toByteArray())
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0xFE78EECCU
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.UInt
|
||||
import kotlin.collections.List
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_payments_CurrencyRates : TlGen_Object {
|
||||
public data class TL_payments_currencyRates(
|
||||
public val rates: List<TlGen_CurrencyRate>,
|
||||
) : TlGen_payments_CurrencyRates() {
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
TlGen_Vector.serialize(stream, rates)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0xBBCCE4C2U
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.UInt
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_toncenter_ApiResponse : TlGen_Object {
|
||||
public data class TL_toncenter_apiResponse(
|
||||
public val response: TlGen_DataJSON,
|
||||
) : TlGen_toncenter_ApiResponse() {
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
response.serializeToStream(stream)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0xAC8DFE19U
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.Int
|
||||
import kotlin.String
|
||||
import kotlin.UInt
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_toncenter_StreamingUrl : TlGen_Object {
|
||||
public data class TL_toncenter_streamingUrl(
|
||||
public val url: String,
|
||||
public val expires: Int,
|
||||
) : TlGen_toncenter_StreamingUrl() {
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeString(url)
|
||||
stream.writeInt32(expires)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x19887601U
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.Byte
|
||||
import kotlin.UInt
|
||||
import kotlin.collections.List
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_wallet_EncryptedSecretPhrasePart : TlGen_Object {
|
||||
public data class TL_wallet_encryptedSecretPhrasePart(
|
||||
public val `data`: List<Byte>,
|
||||
) : TlGen_wallet_EncryptedSecretPhrasePart() {
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeByteArray(data.toByteArray())
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x18E82537U
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.Boolean
|
||||
import kotlin.String
|
||||
import kotlin.UInt
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_wallet_ExistingBalance : TlGen_Object {
|
||||
public data class TL_wallet_existingBalance(
|
||||
public val has_balance: Boolean,
|
||||
public val url: String,
|
||||
) : TlGen_wallet_ExistingBalance() {
|
||||
internal val flags: UInt
|
||||
get() {
|
||||
var result = 0U
|
||||
if (has_balance) result = result or 1U
|
||||
return result
|
||||
}
|
||||
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt32(flags.toInt())
|
||||
stream.writeString(url)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0xBDE90A8DU
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.Byte
|
||||
import kotlin.Int
|
||||
import kotlin.UInt
|
||||
import kotlin.collections.List
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_wallet_HolderDc : TlGen_Object {
|
||||
public data class TL_wallet_holderDc(
|
||||
public val dc: Int,
|
||||
public val public_key: List<Byte>,
|
||||
) : TlGen_wallet_HolderDc() {
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt32(dc)
|
||||
stream.writeByteArray(public_key.toByteArray())
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0xF9D612EFU
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.String
|
||||
import kotlin.UInt
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_wallet_NftAttribute : TlGen_Object {
|
||||
public data class TL_wallet_nftAttribute(
|
||||
public val trait_type: String,
|
||||
public val `value`: String,
|
||||
) : TlGen_wallet_NftAttribute() {
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeString(trait_type)
|
||||
stream.writeString(value)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x4C1EF10EU
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.String
|
||||
import kotlin.UInt
|
||||
import kotlin.collections.List
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_wallet_NftItem : TlGen_Object {
|
||||
public data class TL_wallet_nftItem(
|
||||
public val collection_address: String?,
|
||||
public val address: String,
|
||||
public val owner_address: String,
|
||||
public val index: String,
|
||||
public val name: String?,
|
||||
public val description: String?,
|
||||
public val image: TlGen_WebDocument?,
|
||||
public val image_small: TlGen_WebDocument?,
|
||||
public val content_url: TlGen_WebDocument?,
|
||||
public val lottie: TlGen_WebDocument?,
|
||||
public val attributes: List<TlGen_wallet_NftAttribute>?,
|
||||
public val extra: TlGen_DataJSON?,
|
||||
) : TlGen_wallet_NftItem() {
|
||||
internal val flags: UInt
|
||||
get() {
|
||||
var result = 0U
|
||||
if (collection_address != null) result = result or 1U
|
||||
if (name != null) result = result or 2U
|
||||
if (description != null) result = result or 4U
|
||||
if (image != null) result = result or 8U
|
||||
if (image_small != null) result = result or 16U
|
||||
if (content_url != null) result = result or 32U
|
||||
if (lottie != null) result = result or 64U
|
||||
if (attributes != null) result = result or 128U
|
||||
if (extra != null) result = result or 256U
|
||||
return result
|
||||
}
|
||||
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt32(flags.toInt())
|
||||
collection_address?.let { stream.writeString(it) }
|
||||
stream.writeString(address)
|
||||
stream.writeString(owner_address)
|
||||
stream.writeString(index)
|
||||
name?.let { stream.writeString(it) }
|
||||
description?.let { stream.writeString(it) }
|
||||
image?.serializeToStream(stream)
|
||||
image_small?.serializeToStream(stream)
|
||||
content_url?.serializeToStream(stream)
|
||||
lottie?.serializeToStream(stream)
|
||||
attributes?.let { TlGen_Vector.serialize(stream, it) }
|
||||
extra?.serializeToStream(stream)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x3441FD1CU
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.String
|
||||
import kotlin.UInt
|
||||
import kotlin.collections.List
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_wallet_NftItems : TlGen_Object {
|
||||
public data class TL_wallet_nftItems(
|
||||
public val items: List<TlGen_wallet_NftItem>,
|
||||
public val next_offset: String?,
|
||||
) : TlGen_wallet_NftItems() {
|
||||
internal val flags: UInt
|
||||
get() {
|
||||
var result = 0U
|
||||
if (next_offset != null) result = result or 1U
|
||||
return result
|
||||
}
|
||||
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt32(flags.toInt())
|
||||
TlGen_Vector.serialize(stream, items)
|
||||
next_offset?.let { stream.writeString(it) }
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x794D486FU
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.Int
|
||||
import kotlin.String
|
||||
import kotlin.UInt
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_wallet_ProofChallenge : TlGen_Object {
|
||||
public data class TL_wallet_proofChallenge(
|
||||
public val payload: String,
|
||||
public val expires: Int,
|
||||
public val domain: String,
|
||||
) : TlGen_wallet_ProofChallenge() {
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeString(payload)
|
||||
stream.writeInt32(expires)
|
||||
stream.writeString(domain)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x99E41707U
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.Int
|
||||
import kotlin.String
|
||||
import kotlin.UInt
|
||||
import kotlin.collections.List
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_wallet_SecretPhraseParts : TlGen_Object {
|
||||
public data class TL_wallet_secretPhraseParts(
|
||||
public val token: String,
|
||||
public val dcs: List<Int>,
|
||||
) : TlGen_wallet_SecretPhraseParts() {
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeString(token)
|
||||
TlGen_Vector.serializeInt(stream, dcs)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0xE6D0EF01U
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.Byte
|
||||
import kotlin.Long
|
||||
import kotlin.UInt
|
||||
import kotlin.collections.List
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_wallet_TonConnectChallenge : TlGen_Object {
|
||||
public data class TL_wallet_tonConnectChallenge(
|
||||
public val challenge: List<Byte>,
|
||||
public val event_id: Long,
|
||||
) : TlGen_wallet_TonConnectChallenge() {
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeByteArray(challenge.toByteArray())
|
||||
stream.writeInt64(event_id)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x4BC89693U
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.UInt
|
||||
import kotlin.collections.List
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_wallet_TonConnectPending : TlGen_Object {
|
||||
public data class TL_wallet_tonConnectPending(
|
||||
public val session: TlGen_TonConnectSession,
|
||||
public val requests: List<TlGen_TonConnectRequest>,
|
||||
) : TlGen_wallet_TonConnectPending() {
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
session.serializeToStream(stream)
|
||||
TlGen_Vector.serialize(stream, requests)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x85C0F124U
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.UInt
|
||||
import kotlin.collections.List
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_wallet_TonConnectSessions : TlGen_Object {
|
||||
public data class TL_wallet_tonConnectSessions(
|
||||
public val sessions: List<TlGen_TonConnectSession>,
|
||||
) : TlGen_wallet_TonConnectSessions() {
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
TlGen_Vector.serialize(stream, sessions)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x0E1F6896U
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.Long
|
||||
import kotlin.String
|
||||
import kotlin.UInt
|
||||
import kotlin.collections.List
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_wallet_Transactions : TlGen_Object {
|
||||
public data class TL_wallet_transactions(
|
||||
public val balance: Long,
|
||||
public val transactions: List<TlGen_WalletTransaction>,
|
||||
public val next_offset: String?,
|
||||
public val chats: List<TlGen_Chat>,
|
||||
public val users: List<TlGen_User>,
|
||||
) : TlGen_wallet_Transactions() {
|
||||
internal val flags: UInt
|
||||
get() {
|
||||
var result = 0U
|
||||
if (next_offset != null) result = result or 1U
|
||||
return result
|
||||
}
|
||||
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
stream.writeInt32(flags.toInt())
|
||||
stream.writeInt64(balance)
|
||||
TlGen_Vector.serialize(stream, transactions)
|
||||
next_offset?.let { stream.writeString(it) }
|
||||
TlGen_Vector.serialize(stream, chats)
|
||||
TlGen_Vector.serialize(stream, users)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x4322D5A5U
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package org.telegram.tgnet.model.generated
|
||||
|
||||
import kotlin.UInt
|
||||
import kotlin.collections.List
|
||||
import org.telegram.tgnet.OutputSerializedData
|
||||
import org.telegram.tgnet.model.TlGen_Object
|
||||
import org.telegram.tgnet.model.TlGen_Vector
|
||||
|
||||
public sealed class TlGen_wallet_UserAddresses : TlGen_Object {
|
||||
public data class TL_wallet_userAddresses(
|
||||
public val addresses: List<TlGen_WalletUserAddress>,
|
||||
public val users: List<TlGen_User>,
|
||||
) : TlGen_wallet_UserAddresses() {
|
||||
public override fun serializeToStream(stream: OutputSerializedData) {
|
||||
stream.writeInt32(MAGIC.toInt())
|
||||
TlGen_Vector.serialize(stream, addresses)
|
||||
TlGen_Vector.serialize(stream, users)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val MAGIC: UInt = 0x928E7B55U
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
TMessagesProj_AppTests/tlscheme/231.json
Normal file
1
TMessagesProj_AppTests/tlscheme/231.json
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -23,7 +23,7 @@ import java.io.File
|
|||
|
||||
abstract class GenerateSchemeTask : DefaultTask() {
|
||||
companion object {
|
||||
const val LAYER = 229;
|
||||
const val LAYER = 231;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@
|
|||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
#Sat Mar 12 05:53:50 MSK 2016
|
||||
APP_VERSION_CODE=7158
|
||||
APP_VERSION_NAME=13.0.0
|
||||
APP_VERSION_CODE=7166
|
||||
APP_VERSION_NAME=13.0.1
|
||||
APP_PACKAGE=org.telegram.messenger
|
||||
IS_PRIVATE=false
|
||||
RELEASE_KEY_PASSWORD=android
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue