update to 10.10.1 (4583)

This commit is contained in:
dkaraush 2024-04-01 11:45:21 +04:00
parent 3a822b15f2
commit a906f12aae
66 changed files with 782 additions and 300 deletions

View file

@ -1490,6 +1490,13 @@ public class DatabaseMigrationHelper {
version = 151; version = 151;
} }
if (version == 151) {
database.executeFast("ALTER TABLE profile_stories ADD COLUMN seen INTEGER default 0;").stepThis().dispose();
database.executeFast("PRAGMA user_version = 152").stepThis().dispose();
version = 152;
}
return version; return version;
} }

View file

@ -673,7 +673,7 @@ public class FileUploadOperation {
} }
}), forceSmallFile ? ConnectionsManager.RequestFlagCanCompress : 0, ConnectionsManager.DEFAULT_DATACENTER_ID, connectionType, true); }), forceSmallFile ? ConnectionsManager.RequestFlagCanCompress : 0, ConnectionsManager.DEFAULT_DATACENTER_ID, connectionType, true);
if (BuildVars.LOGS_ENABLED) { if (BuildVars.LOGS_ENABLED) {
FileLog.d("debug_uploading: " + " send reqId " + requestToken[0] + " " + uploadingFilePath); FileLog.d("debug_uploading: " + " send reqId " + requestToken[0] + " " + uploadingFilePath + " file_part=" + currentRequestPartNum + " isBig=" + isBigFile + " file_id=" + currentFileId);
} }
requestTokens.put(requestNumFinal, requestToken[0]); requestTokens.put(requestNumFinal, requestToken[0]);
} }

View file

@ -3836,8 +3836,8 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
} }
} }
public void prepareResumedRecording(int currentAccount, MediaDataController.DraftVoice draft, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TL_stories.StoryItem replyStory, int guid, boolean manual, String query_shortcut, int query_shortcut_id) { public void prepareResumedRecording(int currentAccount, MediaDataController.DraftVoice draft, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TL_stories.StoryItem replyStory, int guid, String query_shortcut, int query_shortcut_id) {
manualRecording = manual; manualRecording = false;
requestAudioFocus(true); requestAudioFocus(true);
recordQueue.cancelRunnable(recordStartRunnable); recordQueue.cancelRunnable(recordStartRunnable);
recordQueue.postRunnable(() -> { recordQueue.postRunnable(() -> {
@ -4151,6 +4151,22 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
}); });
} }
public void cleanRecording(boolean delete) {
recordingAudio = null;
AutoDeleteMediaTask.unlockFile(recordingAudioFile);
if (delete && recordingAudioFile != null) {
try {
recordingAudioFile.delete();
} catch (Exception e) {
FileLog.e(e);
}
}
recordingAudioFile = null;
manualRecording = false;
raiseToEarRecord = false;
ignoreOnPause = false;
}
private void stopRecordingInternal(final int send, boolean notify, int scheduleDate, boolean once) { private void stopRecordingInternal(final int send, boolean notify, int scheduleDate, boolean once) {
if (send != 0) { if (send != 0) {
final TLRPC.TL_document audioToSend = recordingAudio; final TLRPC.TL_document audioToSend = recordingAudio;

View file

@ -242,7 +242,7 @@ public class MessagesController extends BaseController implements NotificationCe
public boolean dialogFiltersLoaded; public boolean dialogFiltersLoaded;
public ArrayList<TLRPC.TL_dialogFilterSuggested> suggestedFilters = new ArrayList<>(); public ArrayList<TLRPC.TL_dialogFilterSuggested> suggestedFilters = new ArrayList<>();
private LongSparseArray<ArrayList<TLRPC.Updates>> updatesQueueChannels = new LongSparseArray<>(); private final LongSparseArray<ArrayList<TLRPC.Updates>> updatesQueueChannels = new LongSparseArray<>();
private LongSparseLongArray updatesStartWaitTimeChannels = new LongSparseLongArray(); private LongSparseLongArray updatesStartWaitTimeChannels = new LongSparseLongArray();
private LongSparseIntArray channelsPts = new LongSparseIntArray(); private LongSparseIntArray channelsPts = new LongSparseIntArray();
private LongSparseArray<Boolean> gettingDifferenceChannels = new LongSparseArray<>(); private LongSparseArray<Boolean> gettingDifferenceChannels = new LongSparseArray<>();
@ -13485,9 +13485,11 @@ public class MessagesController extends BaseController implements NotificationCe
}); });
return; return;
} }
AndroidUtilities.runOnUIThread(() -> {
if (processInvitedUsers != null) { if (processInvitedUsers != null) {
processInvitedUsers.run(null); processInvitedUsers.run(null);
} }
});
if ("USER_ALREADY_PARTICIPANT".equals(error.text) && ignoreIfAlreadyExists) { if ("USER_ALREADY_PARTICIPANT".equals(error.text) && ignoreIfAlreadyExists) {
if (onFinishRunnable != null) { if (onFinishRunnable != null) {
AndroidUtilities.runOnUIThread(onFinishRunnable); AndroidUtilities.runOnUIThread(onFinishRunnable);
@ -13523,9 +13525,11 @@ public class MessagesController extends BaseController implements NotificationCe
updates = (TLRPC.Updates) response; updates = (TLRPC.Updates) response;
} else { } else {
FileLog.e("unexpected " + response + " in addUserToChat"); FileLog.e("unexpected " + response + " in addUserToChat");
AndroidUtilities.runOnUIThread(() -> {
if (processInvitedUsers != null) { if (processInvitedUsers != null) {
processInvitedUsers.run(null); processInvitedUsers.run(null);
} }
});
return; return;
} }
for (int a = 0; a < updates.updates.size(); a++) { for (int a = 0; a < updates.updates.size(); a++) {

View file

@ -104,7 +104,7 @@ public class MessagesStorage extends BaseController {
} }
} }
public final static int LAST_DB_VERSION = 151; public final static int LAST_DB_VERSION = 152;
private boolean databaseMigrationInProgress; private boolean databaseMigrationInProgress;
public boolean showClearDatabaseAlert; public boolean showClearDatabaseAlert;
private LongSparseIntArray dialogIsForum = new LongSparseIntArray(); private LongSparseIntArray dialogIsForum = new LongSparseIntArray();
@ -698,7 +698,7 @@ public class MessagesStorage extends BaseController {
database.executeFast("CREATE TABLE stories (dialog_id INTEGER, story_id INTEGER, data BLOB, custom_params BLOB, PRIMARY KEY (dialog_id, story_id));").stepThis().dispose(); database.executeFast("CREATE TABLE stories (dialog_id INTEGER, story_id INTEGER, data BLOB, custom_params BLOB, PRIMARY KEY (dialog_id, story_id));").stepThis().dispose();
database.executeFast("CREATE TABLE stories_counter (dialog_id INTEGER PRIMARY KEY, count INTEGER, max_read INTEGER);").stepThis().dispose(); database.executeFast("CREATE TABLE stories_counter (dialog_id INTEGER PRIMARY KEY, count INTEGER, max_read INTEGER);").stepThis().dispose();
database.executeFast("CREATE TABLE profile_stories (dialog_id INTEGER, story_id INTEGER, data BLOB, type INTEGER, PRIMARY KEY(dialog_id, story_id));").stepThis().dispose(); database.executeFast("CREATE TABLE profile_stories (dialog_id INTEGER, story_id INTEGER, data BLOB, type INTEGER, seen INTEGER, PRIMARY KEY(dialog_id, story_id));").stepThis().dispose();
database.executeFast("CREATE TABLE story_drafts (id INTEGER PRIMARY KEY, date INTEGER, data BLOB, type INTEGER);").stepThis().dispose(); database.executeFast("CREATE TABLE story_drafts (id INTEGER PRIMARY KEY, date INTEGER, data BLOB, type INTEGER);").stepThis().dispose();

View file

@ -3,9 +3,9 @@ package org.telegram.messenger;
public class SegmentTree { public class SegmentTree {
private Node[] heap; private Node[] heap;
private int[] array; private long[] array;
public SegmentTree(int[] array) { public SegmentTree(long[] array) {
this.array = array; this.array = array;
if (array.length < 30) { if (array.length < 30) {
return; return;
@ -37,9 +37,9 @@ public class SegmentTree {
} }
} }
public int rMaxQ(int from, int to) { public long rMaxQ(int from, int to) {
if (array.length < 30) { if (array.length < 30) {
int max = Integer.MIN_VALUE; long max = Long.MIN_VALUE;
if (from < 0) from = 0; if (from < 0) from = 0;
if (to > array.length - 1) to = array.length - 1; if (to > array.length - 1) to = array.length - 1;
for (int i = from; i <= to; i++) { for (int i = from; i <= to; i++) {
@ -50,7 +50,7 @@ public class SegmentTree {
return rMaxQ(1, from, to); return rMaxQ(1, from, to);
} }
private int rMaxQ(int v, int from, int to) { private long rMaxQ(int v, int from, int to) {
Node n = heap[v]; Node n = heap[v];
//If you did a range update that contained this node, you can infer the Min value without going down the tree //If you did a range update that contained this node, you can infer the Min value without going down the tree
if (n.pendingVal != null && contains(n.from, n.to, from, to)) { if (n.pendingVal != null && contains(n.from, n.to, from, to)) {
@ -63,8 +63,8 @@ public class SegmentTree {
if (intersects(from, to, n.from, n.to)) { if (intersects(from, to, n.from, n.to)) {
propagate(v); propagate(v);
int leftMin = rMaxQ(2 * v, from, to); final long leftMin = rMaxQ(2 * v, from, to);
int rightMin = rMaxQ(2 * v + 1, from, to); final long rightMin = rMaxQ(2 * v + 1, from, to);
return Math.max(leftMin, rightMin); return Math.max(leftMin, rightMin);
} }
@ -72,9 +72,9 @@ public class SegmentTree {
return 0; return 0;
} }
public int rMinQ(int from, int to) { public long rMinQ(int from, int to) {
if (array.length < 30) { if (array.length < 30) {
int min = Integer.MAX_VALUE; long min = Long.MAX_VALUE;
if (from < 0) from = 0; if (from < 0) from = 0;
if (to > array.length - 1) to = array.length - 1; if (to > array.length - 1) to = array.length - 1;
for (int i = from; i <= to; i++) { for (int i = from; i <= to; i++) {
@ -85,7 +85,7 @@ public class SegmentTree {
return rMinQ(1, from, to); return rMinQ(1, from, to);
} }
private int rMinQ(int v, int from, int to) { private long rMinQ(int v, int from, int to) {
Node n = heap[v]; Node n = heap[v];
//If you did a range update that contained this node, you can infer the Min value without going down the tree //If you did a range update that contained this node, you can infer the Min value without going down the tree
if (n.pendingVal != null && contains(n.from, n.to, from, to)) { if (n.pendingVal != null && contains(n.from, n.to, from, to)) {
@ -98,8 +98,8 @@ public class SegmentTree {
if (intersects(from, to, n.from, n.to)) { if (intersects(from, to, n.from, n.to)) {
propagate(v); propagate(v);
int leftMin = rMinQ(2 * v, from, to); long leftMin = rMinQ(2 * v, from, to);
int rightMin = rMinQ(2 * v + 1, from, to); long rightMin = rMinQ(2 * v + 1, from, to);
return Math.min(leftMin, rightMin); return Math.min(leftMin, rightMin);
} }
@ -136,9 +136,9 @@ public class SegmentTree {
} }
static class Node { static class Node {
int sum; long sum;
int max; long max;
int min; long min;
Integer pendingVal = null; Integer pendingVal = null;
int from; int from;

View file

@ -445,6 +445,9 @@ public class WebmEncoder {
if (bitmap != null) { if (bitmap != null) {
entity.matrix.postScale(1f / bitmap.getWidth(), 1f / bitmap.getHeight()); entity.matrix.postScale(1f / bitmap.getWidth(), 1f / bitmap.getHeight());
} }
if ((entity.subType & 2) != 0) {
entity.matrix.postScale(-1, 1, .5f, .5f);
}
entity.matrix.postScale(entity.width * W, entity.height * H); entity.matrix.postScale(entity.width * W, entity.height * H);
entity.matrix.postTranslate(entity.x * W, entity.y * H); entity.matrix.postTranslate(entity.x * W, entity.y * H);
entity.matrix.postRotate((float) (-entity.rotation / Math.PI * 180), (entity.x + entity.width) * W, (entity.x + entity.height) * H); entity.matrix.postRotate((float) (-entity.rotation / Math.PI * 180), (entity.x + entity.width) * W, (entity.x + entity.height) * H);

View file

@ -1128,6 +1128,28 @@ public class TL_stories {
} }
} }
public static class TL_stories_incrementStoryViews extends TLObject {
public static final int constructor = 0xb2028afb;
public TLRPC.InputPeer peer;
public ArrayList<Integer> id = new ArrayList<>();
public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) {
return TLRPC.Bool.TLdeserialize(stream, constructor, exception);
}
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
peer.serializeToStream(stream);
stream.writeInt32(0x1cb5c415);
int count = id.size();
stream.writeInt32(count);
for (int a = 0; a < count; a++) {
stream.writeInt32(id.get(a));
}
}
}
public static class TL_stories_getStoryViewsList extends TLObject { public static class TL_stories_getStoryViewsList extends TLObject {
public static final int constructor = 0x7ed23c57; public static final int constructor = 0x7ed23c57;

View file

@ -1945,6 +1945,13 @@ public class ActionBarMenuItem extends FrameLayout {
} }
} }
public void setSubItemShown(int id, boolean show) {
if (show)
showSubItem(id);
else
hideSubItem(id);
}
public int getVisibleSubItemsCount() { public int getVisibleSubItemsCount() {
int count = 0; int count = 0;
for (int i = 0; i < popupLayout.getItemsCount(); ++i) { for (int i = 0; i < popupLayout.getItemsCount(); ++i) {

View file

@ -167,6 +167,7 @@ public class UnconfirmedAuthHintCell extends FrameLayout {
noButton.setOnClickListener(v -> { noButton.setOnClickListener(v -> {
noButton.setLoading(true); noButton.setLoading(true);
MessagesController.getInstance(currentAccount).getUnconfirmedAuthController().deny(auths, success -> { MessagesController.getInstance(currentAccount).getUnconfirmedAuthController().deny(auths, success -> {
if (LaunchActivity.isActive)
showLoginPreventedSheet(success); showLoginPreventedSheet(success);
noButton.setLoading(false); noButton.setLoading(false);
MessagesController.getInstance(currentAccount).getUnconfirmedAuthController().cleanup(); MessagesController.getInstance(currentAccount).getUnconfirmedAuthController().cleanup();

View file

@ -374,7 +374,7 @@ public class ChannelMonetizationLayout extends FrameLayout {
formatter.setGroupingUsed(false); formatter.setGroupingUsed(false);
} }
formatter.setMaximumFractionDigits(crypto_amount / 1_000_000_000.0 > 1.5 ? 2 : 6); formatter.setMaximumFractionDigits(crypto_amount / 1_000_000_000.0 > 1.5 ? 2 : 6);
SpannableStringBuilder ssb = new SpannableStringBuilder(replaceTON("TON " + formatter.format(crypto_amount / 1_000_000_000.0), balanceTitle.getPaint())); SpannableStringBuilder ssb = new SpannableStringBuilder(replaceTON("TON " + formatter.format(crypto_amount / 1_000_000_000.0), balanceTitle.getPaint(), .9f, true));
int index = TextUtils.indexOf(ssb, "."); int index = TextUtils.indexOf(ssb, ".");
if (index >= 0) { if (index >= 0) {
ssb.setSpan(balanceTitleSizeSpan, index, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); ssb.setSpan(balanceTitleSizeSpan, index, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
@ -491,7 +491,7 @@ public class ChannelMonetizationLayout extends FrameLayout {
} }
items.add(UItem.asCenterShadow(titleInfo)); items.add(UItem.asCenterShadow(titleInfo));
if (impressionsChart != null && !impressionsChart.isEmpty) { if (impressionsChart != null && !impressionsChart.isEmpty) {
items.add(UItem.asChart(StatisticActivity.VIEW_TYPE_LINEAR, stats_dc, impressionsChart)); items.add(UItem.asChart(StatisticActivity.VIEW_TYPE_BAR_LINEAR, stats_dc, impressionsChart));
items.add(UItem.asShadow(-1, null)); items.add(UItem.asShadow(-1, null));
} }
if (revenueChart != null && !revenueChart.isEmpty) { if (revenueChart != null && !revenueChart.isEmpty) {
@ -557,10 +557,10 @@ public class ChannelMonetizationLayout extends FrameLayout {
private void loadTransactions() { private void loadTransactions() {
if (loadingTransactions) return; if (loadingTransactions) return;
if (transactions.size() >= transactionsTotalCount && transactionsTotalCount != 0) return; if (transactions.size() >= transactionsTotalCount && transactionsTotalCount != 0) return;
TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialogId); // TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialogId);
if (chat == null || !chat.creator) { // if (chat == null || !chat.creator) {
return; // return;
} // }
loadingTransactions = true; loadingTransactions = true;
TL_stats.TL_getBroadcastRevenueTransactions req = new TL_stats.TL_getBroadcastRevenueTransactions(); TL_stats.TL_getBroadcastRevenueTransactions req = new TL_stats.TL_getBroadcastRevenueTransactions();
@ -608,25 +608,33 @@ public class ChannelMonetizationLayout extends FrameLayout {
public static CharSequence replaceTON(CharSequence text, TextPaint textPaint) { public static CharSequence replaceTON(CharSequence text, TextPaint textPaint) {
return replaceTON(text, textPaint, 1f, true); return replaceTON(text, textPaint, 1f, true);
} }
public static CharSequence replaceTON(CharSequence text, TextPaint textPaint, boolean animated) { public static CharSequence replaceTON(CharSequence text, TextPaint textPaint, boolean large) {
return replaceTON(text, textPaint, 1f, animated); return replaceTON(text, textPaint, 1f, large);
} }
public static CharSequence replaceTON(CharSequence text, TextPaint textPaint, float scale, boolean animated) {
public static CharSequence replaceTON(CharSequence text, TextPaint textPaint, float scale, boolean large) {
return replaceTON(text, textPaint, scale, 0, large);
}
public static CharSequence replaceTON(CharSequence text, TextPaint textPaint, float scale, float translateY, boolean large) {
if (ChannelMonetizationLayout.tonString == null) { if (ChannelMonetizationLayout.tonString == null) {
ChannelMonetizationLayout.tonString = new HashMap<>(); ChannelMonetizationLayout.tonString = new HashMap<>();
} }
final int key = textPaint.getFontMetricsInt().bottom * (animated ? 1 : -1); final int key = textPaint.getFontMetricsInt().bottom * (large ? 1 : -1) * (int) (100 * scale);
SpannableString tonString = ChannelMonetizationLayout.tonString.get(key); SpannableString tonString = ChannelMonetizationLayout.tonString.get(key);
if (tonString == null) { if (tonString == null) {
tonString = new SpannableString("T"); tonString = new SpannableString("T");
if (animated) { if (large) {
AnimatedEmojiSpan span = new AnimatedEmojiSpan(DIAMOND_EMOJI, scale, textPaint.getFontMetricsInt()); ColoredImageSpan span = new ColoredImageSpan(R.drawable.ton);
span.emoji = "💎"; span.setScale(scale, scale);
span.cacheType = AnimatedEmojiDrawable.CACHE_TYPE_STANDARD_EMOJI; span.setColorKey(Theme.key_windowBackgroundWhiteBlueText2);
span.setRelativeSize(textPaint.getFontMetricsInt());
span.spaceScaleX = .9f;
tonString.setSpan(span, 0, tonString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); tonString.setSpan(span, 0, tonString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} else { } else {
ColoredImageSpan span = new ColoredImageSpan(R.drawable.mini_ton); ColoredImageSpan span = new ColoredImageSpan(R.drawable.mini_ton);
span.setTranslateY(-dp(.66f)); span.setScale(scale, scale);
span.setTranslateY(translateY);
span.spaceScaleX = .95f; span.spaceScaleX = .95f;
tonString.setSpan(span, 0, tonString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); tonString.setSpan(span, 0, tonString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} }
@ -1088,9 +1096,11 @@ public class ChannelMonetizationLayout extends FrameLayout {
textView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); textView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider));
SpannableString animatedDiamond = new SpannableString("💎"); SpannableString animatedDiamond = new SpannableString("💎");
AnimatedEmojiSpan span = new AnimatedEmojiSpan(DIAMOND_EMOJI, .98f, textView.getPaint().getFontMetricsInt()); ColoredImageSpan span = new ColoredImageSpan(R.drawable.ton);
span.emoji = "💎"; span.setScale(.9f, .9f);
span.cacheType = AnimatedEmojiDrawable.CACHE_TYPE_ALERT_STANDARD_EMOJI; span.setColorKey(Theme.key_windowBackgroundWhiteBlueText2);
span.setRelativeSize(textView.getPaint().getFontMetricsInt());
span.spaceScaleX = .9f;
animatedDiamond.setSpan(span, 0, animatedDiamond.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); animatedDiamond.setSpan(span, 0, animatedDiamond.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(AndroidUtilities.replaceCharSequence("💎", getString(R.string.MonetizationInfoTONTitle), animatedDiamond)); textView.setText(AndroidUtilities.replaceCharSequence("💎", getString(R.string.MonetizationInfoTONTitle), animatedDiamond));
layout.addView(textView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 8, 20, 8, 0)); layout.addView(textView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 8, 20, 8, 0));

View file

@ -66,7 +66,7 @@ public class BarChartView extends BaseChartView<ChartData, BarViewData> {
} else { } else {
p = chartData.xPercentage[1] * fullWidth; p = chartData.xPercentage[1] * fullWidth;
} }
int[] y = line.line.y; final long[] y = line.line.y;
int j = 0; int j = 0;
float selectedX = 0f; float selectedX = 0f;
@ -148,7 +148,7 @@ public class BarChartView extends BaseChartView<ChartData, BarViewData> {
} else { } else {
p = chartData.xPercentage[1] * pickerWidth; p = chartData.xPercentage[1] * pickerWidth;
} }
int[] y = line.line.y; final long[] y = line.line.y;
float a = line.alpha; float a = line.alpha;

View file

@ -39,6 +39,7 @@ import org.telegram.ui.Components.CubicBezierInterpolator;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List;
public abstract class BaseChartView<T extends ChartData, L extends LineViewData> extends View implements ChartPickerDelegate.Listener { public abstract class BaseChartView<T extends ChartData, L extends LineViewData> extends View implements ChartPickerDelegate.Listener {
@ -293,7 +294,7 @@ public abstract class BaseChartView<T extends ChartData, L extends LineViewData>
} }
if (legendShowing && selectedIndex < chartData.x.length) { if (legendShowing && selectedIndex < chartData.x.length) {
legendSignatureView.setData(selectedIndex, chartData.x[selectedIndex], (ArrayList<LineViewData>) lines, false, chartData.yTooltipFormatter); legendSignatureView.setData(selectedIndex, chartData.x[selectedIndex], (ArrayList<LineViewData>) lines, false, chartData.yTooltipFormatter, chartData.yRate);
} }
invalidatePickerChart = true; invalidatePickerChart = true;
@ -302,6 +303,10 @@ public abstract class BaseChartView<T extends ChartData, L extends LineViewData>
int lastW = 0; int lastW = 0;
int lastH = 0; int lastH = 0;
private Rect exclusionRect = new Rect();
private List<Rect> exclusionRects = new ArrayList<Rect>();
{ exclusionRects.add(exclusionRect); }
@Override @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec); super.onMeasure(widthMeasureSpec, heightMeasureSpec);
@ -332,6 +337,11 @@ public abstract class BaseChartView<T extends ChartData, L extends LineViewData>
onPickerDataChanged(false, true, false); onPickerDataChanged(false, true, false);
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
exclusionRect.set(0, getMeasuredHeight() - (PICKER_PADDING + pikerHeight + PICKER_PADDING), getMeasuredWidth(), getMeasuredHeight());
setSystemGestureExclusionRects(exclusionRects);
}
} }
@ -799,11 +809,11 @@ public abstract class BaseChartView<T extends ChartData, L extends LineViewData>
long lastTime = 0; long lastTime = 0;
private void setMaxMinValue(int newMaxHeight, int newMinHeight, boolean animated) { private void setMaxMinValue(long newMaxHeight, long newMinHeight, boolean animated) {
setMaxMinValue(newMaxHeight, newMinHeight, animated, false, false); setMaxMinValue(newMaxHeight, newMinHeight, animated, false, false);
} }
protected void setMaxMinValue(int newMaxHeight, int newMinHeight, boolean animated, boolean force, boolean useAnimator) { protected void setMaxMinValue(long newMaxHeight, long newMinHeight, boolean animated, boolean force, boolean useAnimator) {
boolean heightChanged = true; boolean heightChanged = true;
if ((Math.abs(ChartHorizontalLinesData.lookupHeight(newMaxHeight) - animateToMaxHeight) < thresholdMaxHeight) || newMaxHeight == 0) { if ((Math.abs(ChartHorizontalLinesData.lookupHeight(newMaxHeight) - animateToMaxHeight) < thresholdMaxHeight) || newMaxHeight == 0) {
heightChanged = false; heightChanged = false;
@ -918,7 +928,7 @@ public abstract class BaseChartView<T extends ChartData, L extends LineViewData>
alphaAnimator.start(); alphaAnimator.start();
} }
protected ChartHorizontalLinesData createHorizontalLinesData(int newMaxHeight, int newMinHeight, int formatter) { protected ChartHorizontalLinesData createHorizontalLinesData(long newMaxHeight, long newMinHeight, int formatter) {
return new ChartHorizontalLinesData(newMaxHeight, newMinHeight, useMinHeight, chartData.yRate, formatter, signaturePaint, signaturePaint2); return new ChartHorizontalLinesData(newMaxHeight, newMinHeight, useMinHeight, chartData.yRate, formatter, signaturePaint, signaturePaint2);
} }
@ -1030,7 +1040,7 @@ public abstract class BaseChartView<T extends ChartData, L extends LineViewData>
chartCaptured = false; chartCaptured = false;
onActionUp(); onActionUp();
invalidate(); invalidate();
int min = 0; long min = 0;
if (useMinHeight) min = findMinValue(startXIndex, endXIndex); if (useMinHeight) min = findMinValue(startXIndex, endXIndex);
setMaxMinValue(findMaxValue(startXIndex, endXIndex), min, true, true, false); setMaxMinValue(findMaxValue(startXIndex, endXIndex), min, true, true, false);
return true; return true;
@ -1117,7 +1127,7 @@ public abstract class BaseChartView<T extends ChartData, L extends LineViewData>
public void moveLegend(float offset) { public void moveLegend(float offset) {
if (chartData == null || selectedIndex == -1 || !legendShowing) return; if (chartData == null || selectedIndex == -1 || !legendShowing) return;
legendSignatureView.setData(selectedIndex, chartData.x[selectedIndex], (ArrayList<LineViewData>) lines, false, chartData.yTooltipFormatter); legendSignatureView.setData(selectedIndex, chartData.x[selectedIndex], (ArrayList<LineViewData>) lines, false, chartData.yTooltipFormatter, chartData.yRate);
legendSignatureView.setVisibility(VISIBLE); legendSignatureView.setVisibility(VISIBLE);
legendSignatureView.measure( legendSignatureView.measure(
MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.AT_MOST),
@ -1139,12 +1149,12 @@ public abstract class BaseChartView<T extends ChartData, L extends LineViewData>
); );
} }
public int findMaxValue(int startXIndex, int endXIndex) { public long findMaxValue(int startXIndex, int endXIndex) {
int linesSize = lines.size(); int linesSize = lines.size();
int maxValue = 0; long maxValue = 0;
for (int j = 0; j < linesSize; j++) { for (int j = 0; j < linesSize; j++) {
if (!lines.get(j).enabled) continue; if (!lines.get(j).enabled) continue;
int lineMax = lines.get(j).line.segmentTree.rMaxQ(startXIndex, endXIndex); long lineMax = lines.get(j).line.segmentTree.rMaxQ(startXIndex, endXIndex);
if (lineMax > maxValue) if (lineMax > maxValue)
maxValue = lineMax; maxValue = lineMax;
} }
@ -1152,12 +1162,12 @@ public abstract class BaseChartView<T extends ChartData, L extends LineViewData>
} }
public int findMinValue(int startXIndex, int endXIndex) { public long findMinValue(int startXIndex, int endXIndex) {
int linesSize = lines.size(); int linesSize = lines.size();
int minValue = Integer.MAX_VALUE; long minValue = Long.MAX_VALUE;
for (int j = 0; j < linesSize; j++) { for (int j = 0; j < linesSize; j++) {
if (!lines.get(j).enabled) continue; if (!lines.get(j).enabled) continue;
int lineMin = lines.get(j).line.segmentTree.rMinQ(startXIndex, endXIndex); long lineMin = lines.get(j).line.segmentTree.rMinQ(startXIndex, endXIndex);
if (lineMin < minValue) if (lineMin < minValue)
minValue = lineMin; minValue = lineMin;
} }
@ -1195,12 +1205,16 @@ public abstract class BaseChartView<T extends ChartData, L extends LineViewData>
if (chartData != null) { if (chartData != null) {
updateIndexes(); updateIndexes();
int min = useMinHeight ? findMinValue(startXIndex, endXIndex) : 0; final long min = useMinHeight ? findMinValue(startXIndex, endXIndex) : 0;
setMaxMinValue(findMaxValue(startXIndex, endXIndex), min, false); setMaxMinValue(findMaxValue(startXIndex, endXIndex), min, false);
pickerMaxHeight = 0; pickerMaxHeight = 0;
pickerMinHeight = Integer.MAX_VALUE; pickerMinHeight = Integer.MAX_VALUE;
initPickerMaxHeight(); initPickerMaxHeight();
if (chartData.yTooltipFormatter == ChartData.FORMATTER_TON) {
legendSignatureView.setSize(2 * lines.size());
} else {
legendSignatureView.setSize(lines.size()); legendSignatureView.setSize(lines.size());
}
invalidatePickerChart = true; invalidatePickerChart = true;
updateLineSignature(); updateLineSignature();
@ -1261,7 +1275,7 @@ public abstract class BaseChartView<T extends ChartData, L extends LineViewData>
chartFullWidth = (chartWidth / (pickerDelegate.pickerEnd - pickerDelegate.pickerStart)); chartFullWidth = (chartWidth / (pickerDelegate.pickerEnd - pickerDelegate.pickerStart));
updateIndexes(); updateIndexes();
int min = useMinHeight ? findMinValue(startXIndex, endXIndex) : 0; final long min = useMinHeight ? findMinValue(startXIndex, endXIndex) : 0;
setMaxMinValue(findMaxValue(startXIndex, endXIndex), min, animated, force, useAniamtor); setMaxMinValue(findMaxValue(startXIndex, endXIndex), min, animated, force, useAniamtor);
if (legendShowing && !force) { if (legendShowing && !force) {
@ -1422,13 +1436,13 @@ public abstract class BaseChartView<T extends ChartData, L extends LineViewData>
updatePickerMinMaxHeight(); updatePickerMinMaxHeight();
if (legendShowing) if (legendShowing)
legendSignatureView.setData(selectedIndex, chartData.x[selectedIndex], (ArrayList<LineViewData>) lines, true, chartData.yTooltipFormatter); legendSignatureView.setData(selectedIndex, chartData.x[selectedIndex], (ArrayList<LineViewData>) lines, true, chartData.yTooltipFormatter, chartData.yRate);
} }
protected void updatePickerMinMaxHeight() { protected void updatePickerMinMaxHeight() {
if (!ANIMATE_PICKER_SIZES) return; if (!ANIMATE_PICKER_SIZES) return;
int max = 0; long max = 0;
int min = Integer.MAX_VALUE; long min = Long.MAX_VALUE;
for (LineViewData l : lines) { for (LineViewData l : lines) {
if (l.enabled && l.line.maxValue > max) max = l.line.maxValue; if (l.enabled && l.line.maxValue > max) max = l.line.maxValue;
if (l.enabled && l.line.minValue < min) min = l.line.minValue; if (l.enabled && l.line.minValue < min) min = l.line.minValue;

View file

@ -63,7 +63,7 @@ public class DoubleLinearChartView extends BaseChartView<DoubleLinearChartData,
int j = 0; int j = 0;
int[] y = line.line.y; final long[] y = line.line.y;
line.chartPath.reset(); line.chartPath.reset();
boolean first = true; boolean first = true;
@ -137,7 +137,7 @@ public class DoubleLinearChartView extends BaseChartView<DoubleLinearChartData,
int n = chartData.xPercentage.length; int n = chartData.xPercentage.length;
int j = 0; int j = 0;
int[] y = line.line.y; final long[] y = line.line.y;
line.chartPath.reset(); line.chartPath.reset();
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
@ -263,30 +263,30 @@ public class DoubleLinearChartView extends BaseChartView<DoubleLinearChartData,
@Override @Override
public LineViewData createLineViewData(ChartData.Line line) { public LineViewData createLineViewData(ChartData.Line line) {
return new LineViewData(line, resourcesProvider); return new LineViewData(line, false, resourcesProvider);
} }
public int findMaxValue(int startXIndex, int endXIndex) { public long findMaxValue(int startXIndex, int endXIndex) {
if (lines.isEmpty()) { if (lines.isEmpty()) {
return 0; return 0;
} }
int n = lines.size(); final int n = lines.size();
int max = 0; long max = 0;
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
int localMax = lines.get(i).enabled ? (int) (chartData.lines.get(i).segmentTree.rMaxQ(startXIndex, endXIndex) * chartData.linesK[i]) : 0; long localMax = lines.get(i).enabled ? (long) (chartData.lines.get(i).segmentTree.rMaxQ(startXIndex, endXIndex) * chartData.linesK[i]) : 0;
if (localMax > max) max = localMax; if (localMax > max) max = localMax;
} }
return max; return max;
} }
public int findMinValue(int startXIndex, int endXIndex) { public long findMinValue(int startXIndex, int endXIndex) {
if (lines.isEmpty()) { if (lines.isEmpty()) {
return 0; return 0;
} }
int n = lines.size(); final int n = lines.size();
int min = Integer.MAX_VALUE; long min = Long.MAX_VALUE;
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
int localMin = lines.get(i).enabled ? (int) (chartData.lines.get(i).segmentTree.rMinQ(startXIndex, endXIndex) * chartData.linesK[i]) : Integer.MAX_VALUE; long localMin = lines.get(i).enabled ? (int) (chartData.lines.get(i).segmentTree.rMinQ(startXIndex, endXIndex) * chartData.linesK[i]) : Integer.MAX_VALUE;
if (localMin < min) min = localMin; if (localMin < min) min = localMin;
} }
return min; return min;
@ -299,12 +299,12 @@ public class DoubleLinearChartView extends BaseChartView<DoubleLinearChartData,
return; return;
} }
int max = 0; long max = 0;
for (LineViewData l : lines) { for (LineViewData l : lines) {
if (l.enabled && l.line.maxValue > max) max = l.line.maxValue; if (l.enabled && l.line.maxValue > max) max = l.line.maxValue;
} }
if (lines.size() > 1) { if (lines.size() > 1) {
max = (int) (max * chartData.linesK[1]); max = (long) (max * chartData.linesK[1]);
} }
if (max > 0 && max != animatedToPickerMaxHeight) { if (max > 0 && max != animatedToPickerMaxHeight) {
@ -324,7 +324,7 @@ public class DoubleLinearChartView extends BaseChartView<DoubleLinearChartData,
} }
@Override @Override
protected ChartHorizontalLinesData createHorizontalLinesData(int newMaxHeight, int newMinHeight, int formatter) { protected ChartHorizontalLinesData createHorizontalLinesData(long newMaxHeight, long newMinHeight, int formatter) {
float k; float k;
if (chartData.linesK.length < 2) { if (chartData.linesK.length < 2) {
k = 1; k = 1;

View file

@ -0,0 +1,216 @@
package org.telegram.ui.Charts;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import org.telegram.ui.Charts.data.ChartData;
import org.telegram.ui.Charts.view_data.LineViewData;
public class LinearBarChartView extends BaseChartView<ChartData, LineViewData> {
public LinearBarChartView(Context context) {
super(context);
}
@Override
protected void init() {
useMinHeight = true;
super.init();
}
@Override
protected void drawChart(Canvas canvas) {
if (chartData != null) {
float fullWidth = (chartWidth / (pickerDelegate.pickerEnd - pickerDelegate.pickerStart));
float offset = fullWidth * (pickerDelegate.pickerStart) - HORIZONTAL_PADDING;
for (int k = 0; k < lines.size(); k++) {
LineViewData line = lines.get(k);
if (!line.enabled && line.alpha == 0) continue;
int j = 0;
float p;
if (chartData.xPercentage.length < 2) {
p = 0f;
} else {
p = chartData.xPercentage[1] * fullWidth;
}
final long[] y = line.line.y;
int additionalPoints = (int) (HORIZONTAL_PADDING / p) + 1;
line.chartPath.reset();
boolean first = true;
int localStart = Math.max(0, startXIndex - additionalPoints);
int localEnd = Math.min(chartData.xPercentage.length - 1, endXIndex + additionalPoints);
for (int i = localStart; i <= localEnd; i++) {
if (y[i] < 0) continue;
float xPoint = chartData.xPercentage[i] * fullWidth - offset;
float yPercentage = ((float) y[i] - currentMinHeight) / (currentMaxHeight - currentMinHeight);
float padding = line.paint.getStrokeWidth() / 2f;
float yPoint = getMeasuredHeight() - chartBottom - padding - (yPercentage) * (getMeasuredHeight() - chartBottom - SIGNATURE_TEXT_HEIGHT - padding);
if (USE_LINES) {
if (j == 0) {
line.linesPath[j++] = xPoint - p / 2f;
line.linesPath[j++] = yPoint;
line.linesPath[j++] = xPoint + p / 2f;
line.linesPath[j++] = yPoint;
line.linesPath[j++] = xPoint + p / 2f;
line.linesPath[j++] = yPoint;
} else if (i == localEnd) {
line.linesPath[j++] = xPoint - p / 2f;
line.linesPath[j++] = yPoint;
line.linesPath[j++] = xPoint - p / 2f;
line.linesPath[j++] = yPoint;
line.linesPath[j++] = xPoint + p / 2f;
line.linesPath[j++] = yPoint;
line.linesPath[j++] = xPoint + p / 2f;
line.linesPath[j++] = yPoint;
line.linesPath[j++] = xPoint + p / 2f;
line.linesPath[j++] = getMeasuredHeight() - chartBottom - padding;
} else {
line.linesPath[j++] = xPoint - p / 2f;
line.linesPath[j++] = yPoint;
line.linesPath[j++] = xPoint - p / 2f;
line.linesPath[j++] = yPoint;
line.linesPath[j++] = xPoint + p / 2f;
line.linesPath[j++] = yPoint;
line.linesPath[j++] = xPoint + p / 2f;
line.linesPath[j++] = yPoint;
}
} else {
if (first) {
first = false;
line.chartPath.moveTo(xPoint - p / 2f, yPoint);
} else {
line.chartPath.lineTo(xPoint - p / 2f, yPoint);
}
line.chartPath.lineTo(xPoint + p / 2f, yPoint);
}
}
canvas.save();
float transitionAlpha = 1f;
if (transitionMode == TRANSITION_MODE_PARENT) {
transitionAlpha = transitionParams.progress > 0.5f ? 0 : 1f - transitionParams.progress * 2f;
canvas.scale(
1 + 2 * transitionParams.progress, 1f,
transitionParams.pX, transitionParams.pY
);
} else if (transitionMode == TRANSITION_MODE_CHILD) {
transitionAlpha = transitionParams.progress < 0.3f ? 0 : transitionParams.progress;
canvas.save();
canvas.scale(
transitionParams.progress, transitionParams.needScaleY ? transitionParams.progress : 1f,
transitionParams.pX, transitionParams.pY
);
} else if (transitionMode == TRANSITION_MODE_ALPHA_ENTER) {
transitionAlpha = transitionParams.progress;
}
line.paint.setAlpha((int) (255 * line.alpha * transitionAlpha));
if(endXIndex - startXIndex > 100){
line.paint.setStrokeCap(Paint.Cap.SQUARE);
} else {
line.paint.setStrokeCap(Paint.Cap.ROUND);
}
if (!USE_LINES) canvas.drawPath(line.chartPath, line.paint);
else canvas.drawLines(line.linesPath, 0, j, line.paint);
canvas.restore();
}
}
}
@Override
protected void drawPickerChart(Canvas canvas) {
int bottom = getMeasuredHeight() - PICKER_PADDING;
int top = getMeasuredHeight() - pikerHeight - PICKER_PADDING;
int nl = lines.size();
if (chartData != null) {
float p;
if (chartData.xPercentage.length < 2) {
p = 1f;
} else {
p = chartData.xPercentage[1] * pickerWidth;
}
for (int k = 0; k < nl; k++) {
LineViewData line = lines.get(k);
if (!line.enabled && line.alpha == 0) continue;
line.bottomLinePath.reset();
int n = chartData.xPercentage.length;
int j = 0;
final long[] y = line.line.y;
line.chartPath.reset();
for (int i = 0; i < n; i++) {
if (y[i] < 0) continue;
float xPoint = chartData.xPercentage[i] * pickerWidth;
float h = ANIMATE_PICKER_SIZES ? pickerMaxHeight : chartData.maxValue;
float hMin = ANIMATE_PICKER_SIZES ? pickerMinHeight : chartData.minValue;
float yPercentage = (y[i] - hMin) / (h - hMin);
float yPoint = (1f - yPercentage) * pikerHeight;
if (USE_LINES) {
if (j == 0) {
line.linesPathBottom[j++] = xPoint - p / 2f;
line.linesPathBottom[j++] = yPoint;
line.linesPathBottom[j++] = xPoint + p / 2f;
line.linesPathBottom[j++] = yPoint;
line.linesPathBottom[j++] = xPoint + p / 2f;
line.linesPathBottom[j++] = yPoint;
} else if (i == n - 1) {
line.linesPathBottom[j++] = xPoint - p / 2f;
line.linesPathBottom[j++] = yPoint;
line.linesPathBottom[j++] = xPoint - p / 2f;
line.linesPathBottom[j++] = yPoint;
line.linesPathBottom[j++] = xPoint + p / 2f;
line.linesPathBottom[j++] = yPoint;
line.linesPathBottom[j++] = xPoint + p / 2f;
line.linesPathBottom[j++] = yPoint;
line.linesPathBottom[j++] = xPoint + p / 2f;
line.linesPathBottom[j++] = 0;
} else {
line.linesPathBottom[j++] = xPoint - p / 2f;
line.linesPathBottom[j++] = yPoint;
line.linesPathBottom[j++] = xPoint - p / 2f;
line.linesPathBottom[j++] = yPoint;
line.linesPathBottom[j++] = xPoint + p / 2f;
line.linesPathBottom[j++] = yPoint;
line.linesPathBottom[j++] = xPoint + p / 2f;
line.linesPathBottom[j++] = yPoint;
}
} else {
if (i == 0) {
line.bottomLinePath.moveTo(xPoint - p / 2f, yPoint);
} else {
line.bottomLinePath.lineTo(xPoint - p / 2f, yPoint);
}
line.bottomLinePath.lineTo(xPoint + p / 2f, yPoint);
}
}
line.linesPathBottomSize = j;
if (!line.enabled && line.alpha == 0) continue;
line.bottomLinePaint.setAlpha((int) (255 * line.alpha));
if (USE_LINES)
canvas.drawLines(line.linesPathBottom, 0, line.linesPathBottomSize, line.bottomLinePaint);
else
canvas.drawPath(line.bottomLinePath, line.bottomLinePaint);
}
}
}
@Override
public LineViewData createLineViewData(ChartData.Line line) {
return new LineViewData(line, true);
}
}

View file

@ -38,7 +38,7 @@ public class LinearChartView extends BaseChartView<ChartData, LineViewData> {
} else { } else {
p = chartData.xPercentage[1] * fullWidth; p = chartData.xPercentage[1] * fullWidth;
} }
int[] y = line.line.y; final long[] y = line.line.y;
int additionalPoints = (int) (HORIZONTAL_PADDING / p) + 1; int additionalPoints = (int) (HORIZONTAL_PADDING / p) + 1;
line.chartPath.reset(); line.chartPath.reset();
@ -122,7 +122,7 @@ public class LinearChartView extends BaseChartView<ChartData, LineViewData> {
int n = chartData.xPercentage.length; int n = chartData.xPercentage.length;
int j = 0; int j = 0;
int[] y = line.line.y; final long[] y = line.line.y;
line.chartPath.reset(); line.chartPath.reset();
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
@ -166,6 +166,6 @@ public class LinearChartView extends BaseChartView<ChartData, LineViewData> {
@Override @Override
public LineViewData createLineViewData(ChartData.Line line) { public LineViewData createLineViewData(ChartData.Line line) {
return new LineViewData(line); return new LineViewData(line, false);
} }
} }

View file

@ -243,7 +243,7 @@ public class PieChartView extends StackLinearChartView<PieChartViewData> {
LineViewData line = lines.get(k); LineViewData line = lines.get(k);
if (!line.enabled && line.alpha == 0) continue; if (!line.enabled && line.alpha == 0) continue;
int[] y = line.line.y; final long[] y = line.line.y;
float yPercentage; float yPercentage;
if (drawingLinesCount == 1) { if (drawingLinesCount == 1) {

View file

@ -16,7 +16,7 @@ import org.telegram.ui.Charts.view_data.StackBarViewData;
public class StackBarChartView extends BaseChartView<StackBarChartData, StackBarViewData> { public class StackBarChartView extends BaseChartView<StackBarChartData, StackBarViewData> {
private int[] yMaxPoints; private long[] yMaxPoints;
public StackBarChartView(Context context) { public StackBarChartView(Context context) {
this(context, null); this(context, null);
@ -91,7 +91,7 @@ public class StackBarChartView extends BaseChartView<StackBarChartData, StackBar
if (!line.enabled && line.alpha == 0) continue; if (!line.enabled && line.alpha == 0) continue;
int[] y = line.line.y; final long[] y = line.line.y;
float xPoint = p / 2 + chartData.xPercentage[i] * (fullWidth - p) - offset; float xPoint = p / 2 + chartData.xPercentage[i] * (fullWidth - p) - offset;
@ -134,7 +134,7 @@ public class StackBarChartView extends BaseChartView<StackBarChartData, StackBar
if (!line.enabled && line.alpha == 0) continue; if (!line.enabled && line.alpha == 0) continue;
int[] y = line.line.y; final long[] y = line.line.y;
float xPoint = p / 2 + chartData.xPercentage[selectedIndex] * (fullWidth - p) - offset; float xPoint = p / 2 + chartData.xPercentage[selectedIndex] * (fullWidth - p) - offset;
@ -206,7 +206,7 @@ public class StackBarChartView extends BaseChartView<StackBarChartData, StackBar
int step = Math.max(1, Math.round(n / 200f)); int step = Math.max(1, Math.round(n / 200f));
if (yMaxPoints == null || yMaxPoints.length < nl) { if (yMaxPoints == null || yMaxPoints.length < nl) {
yMaxPoints = new int[nl]; yMaxPoints = new long[nl];
} }
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
@ -216,7 +216,7 @@ public class StackBarChartView extends BaseChartView<StackBarChartData, StackBar
for (int k = 0; k < nl; k++) { for (int k = 0; k < nl; k++) {
LineViewData line = lines.get(k); LineViewData line = lines.get(k);
if (!line.enabled && line.alpha == 0) continue; if (!line.enabled && line.alpha == 0) continue;
int y = line.line.y[i]; final long y = line.line.y[i];
if (y > yMaxPoints[k]) yMaxPoints[k] = y; if (y > yMaxPoints[k]) yMaxPoints[k] = y;
} }
@ -263,7 +263,7 @@ public class StackBarChartView extends BaseChartView<StackBarChartData, StackBar
int n = chartData.lines.get(0).y.length; int n = chartData.lines.get(0).y.length;
int k = chartData.lines.size(); int k = chartData.lines.size();
chartData.ySum = new int[n]; chartData.ySum = new long[n];
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
chartData.ySum[i] = 0; chartData.ySum[i] = 0;
for (int j = 0; j < k; j++) { for (int j = 0; j < k; j++) {
@ -280,19 +280,19 @@ public class StackBarChartView extends BaseChartView<StackBarChartData, StackBar
} }
public int findMaxValue(int startXIndex, int endXIndex) { public long findMaxValue(int startXIndex, int endXIndex) {
return chartData.findMax(startXIndex, endXIndex); return chartData.findMax(startXIndex, endXIndex);
} }
protected void updatePickerMinMaxHeight() { protected void updatePickerMinMaxHeight() {
if (!ANIMATE_PICKER_SIZES) return; if (!ANIMATE_PICKER_SIZES) return;
int max = 0; long max = 0;
int n = chartData.x.length; int n = chartData.x.length;
int nl = lines.size(); int nl = lines.size();
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
int h = 0; long h = 0;
for (int k = 0; k < nl; k++) { for (int k = 0; k < nl; k++) {
StackBarViewData l = lines.get(k); StackBarViewData l = lines.get(k);
if (l.enabled) h += l.line.y[i]; if (l.enabled) h += l.line.y[i];
@ -326,7 +326,7 @@ public class StackBarChartView extends BaseChartView<StackBarChartData, StackBar
int n = chartData.x.length; int n = chartData.x.length;
int nl = lines.size(); int nl = lines.size();
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
int h = 0; long h = 0;
for (int k = 0; k < nl; k++) { for (int k = 0; k < nl; k++) {
StackBarViewData l = lines.get(k); StackBarViewData l = lines.get(k);
if (l.enabled) h += l.line.y[i]; if (l.enabled) h += l.line.y[i];

View file

@ -124,7 +124,7 @@ public class StackLinearChartView<T extends StackLinearViewData> extends BaseCha
for (int k = 0; k < lines.size(); k++) { for (int k = 0; k < lines.size(); k++) {
LineViewData line = lines.get(k); LineViewData line = lines.get(k);
if (!line.enabled && line.alpha == 0) continue; if (!line.enabled && line.alpha == 0) continue;
int[] y = line.line.y; final long[] y = line.line.y;
float yPercentage; float yPercentage;
@ -507,7 +507,7 @@ public class StackLinearChartView<T extends StackLinearViewData> extends BaseCha
} }
@Override @Override
public int findMaxValue(int startXIndex, int endXIndex) { public long findMaxValue(int startXIndex, int endXIndex) {
return 100; return 100;
} }
@ -562,7 +562,7 @@ public class StackLinearChartView<T extends StackLinearViewData> extends BaseCha
for (int k = 0; k < lines.size(); k++) { for (int k = 0; k < lines.size(); k++) {
LineViewData line = lines.get(k); LineViewData line = lines.get(k);
if (!line.enabled && line.alpha == 0) continue; if (!line.enabled && line.alpha == 0) continue;
int[] y = line.line.y; final long[] y = line.line.y;
float yPercentage; float yPercentage;

View file

@ -24,8 +24,8 @@ public class ChartData {
public float[] xPercentage; public float[] xPercentage;
public String[] daysLookup; public String[] daysLookup;
public ArrayList<Line> lines = new ArrayList<>(); public ArrayList<Line> lines = new ArrayList<>();
public int maxValue = 0; public long maxValue = 0;
public int minValue = Integer.MAX_VALUE; public long minValue = Long.MAX_VALUE;
public float oneDayPercentage = 0f; public float oneDayPercentage = 0f;
@ -59,9 +59,9 @@ public class ChartData {
lines.add(l); lines.add(l);
int len = a.length() - 1; int len = a.length() - 1;
l.id = a.getString(0); l.id = a.getString(0);
l.y = new int[len]; l.y = new long[len];
for (int j = 0; j < len; j++) { for (int j = 0; j < len; j++) {
l.y[j] = a.getInt(j + 1); l.y[j] = a.getLong(j + 1);
if (l.y[j] > l.maxValue) l.maxValue = l.y[j]; if (l.y[j] > l.maxValue) l.maxValue = l.y[j];
if (l.y[j] < l.minValue) l.minValue = l.y[j]; if (l.y[j] < l.minValue) l.minValue = l.y[j];
} }
@ -247,13 +247,13 @@ public class ChartData {
} }
public class Line { public class Line {
public int[] y; public long[] y;
public SegmentTree segmentTree; public SegmentTree segmentTree;
public String id; public String id;
public String name; public String name;
public int maxValue = 0; public long maxValue = 0;
public int minValue = Integer.MAX_VALUE; public long minValue = Long.MAX_VALUE;
public int colorKey; public int colorKey;
public int color = Color.BLACK; public int color = Color.BLACK;
public int colorDark = Color.WHITE; public int colorDark = Color.WHITE;

View file

@ -16,16 +16,16 @@ public class DoubleLinearChartData extends ChartData {
protected void measure() { protected void measure() {
super.measure(); super.measure();
int n = lines.size(); int n = lines.size();
int max = 0; long max = 0;
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
int m = lines.get(i).maxValue; final long m = lines.get(i).maxValue;
if (m > max) max = m; if (m > max) max = m;
} }
linesK = new float[n]; linesK = new float[n];
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
int m = lines.get(i).maxValue; final long m = lines.get(i).maxValue;
if (max == m) { if (max == m) {
linesK[i] = 1; linesK[i] = 1;
continue; continue;

View file

@ -7,7 +7,7 @@ import org.telegram.messenger.SegmentTree;
public class StackBarChartData extends ChartData { public class StackBarChartData extends ChartData {
public int[] ySum; public long[] ySum;
public SegmentTree ySumSegmentTree; public SegmentTree ySumSegmentTree;
public StackBarChartData(JSONObject jsonObject) throws JSONException { public StackBarChartData(JSONObject jsonObject) throws JSONException {
@ -19,7 +19,7 @@ public class StackBarChartData extends ChartData {
int n = lines.get(0).y.length; int n = lines.get(0).y.length;
int k = lines.size(); int k = lines.size();
ySum = new int[n]; ySum = new long[n];
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
ySum[i] = 0; ySum[i] = 0;
for (int j = 0; j < k; j++) { for (int j = 0; j < k; j++) {
@ -30,7 +30,7 @@ public class StackBarChartData extends ChartData {
ySumSegmentTree = new SegmentTree(ySum); ySumSegmentTree = new SegmentTree(ySum);
} }
public int findMax(int start, int end) { public long findMax(int start, int end) {
return ySumSegmentTree.rMaxQ(start, end); return ySumSegmentTree.rMaxQ(start, end);
} }

View file

@ -9,10 +9,10 @@ import java.util.Arrays;
public class StackLinearChartData extends ChartData { public class StackLinearChartData extends ChartData {
int[] ySum; long[] ySum;
SegmentTree ySumSegmentTree; SegmentTree ySumSegmentTree;
public int[][] simplifiedY; public long[][] simplifiedY;
public int simplifiedSize; public int simplifiedSize;
@ -26,7 +26,7 @@ public class StackLinearChartData extends ChartData {
for (int k = 0; k < lines.size(); k++) { for (int k = 0; k < lines.size(); k++) {
int n = x.length; int n = x.length;
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
int v = lines.get(k).y[i]; long v = lines.get(k).y[i];
totalCount[k] += v; totalCount[k] += v;
if (v == 0) { if (v == 0) {
emptyCount[k]++; emptyCount[k]++;
@ -49,7 +49,7 @@ public class StackLinearChartData extends ChartData {
int n = lines.get(0).y.length; int n = lines.get(0).y.length;
int k = lines.size(); int k = lines.size();
ySum = new int[n]; ySum = new long[n];
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
ySum[i] = 0; ySum[i] = 0;
for (int j = 0; j < k; j++) { for (int j = 0; j < k; j++) {
@ -85,7 +85,7 @@ public class StackLinearChartData extends ChartData {
for (int i = 0; i < data.lines.size(); i++) { for (int i = 0; i < data.lines.size(); i++) {
Line line = new Line(); Line line = new Line();
line.y = new int[n]; line.y = new long[n];
line.id = data.lines.get(i).id; line.id = data.lines.get(i).id;
line.name = data.lines.get(i).name; line.name = data.lines.get(i).name;
line.colorKey = data.lines.get(i).colorKey; line.colorKey = data.lines.get(i).colorKey;
@ -116,9 +116,9 @@ public class StackLinearChartData extends ChartData {
int nl = lines.size(); int nl = lines.size();
int step = Math.max(1, Math.round(n / 140f)); int step = Math.max(1, Math.round(n / 140f));
int maxSize = n / step; int maxSize = n / step;
simplifiedY = new int[nl][maxSize]; simplifiedY = new long[nl][maxSize];
int[] max = new int[nl]; long[] max = new long[nl];
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
for(int k = 0; k < nl; k++) { for(int k = 0; k < nl; k++) {

View file

@ -12,7 +12,7 @@ public class BarViewData extends LineViewData {
public int blendColor = 0; public int blendColor = 0;
public BarViewData(ChartData.Line line) { public BarViewData(ChartData.Line line) {
super(line); super(line, false);
paint.setStyle(Paint.Style.STROKE); paint.setStyle(Paint.Style.STROKE);
unselectedPaint.setStyle(Paint.Style.STROKE); unselectedPaint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(false); paint.setAntiAlias(false);

View file

@ -1,5 +1,7 @@
package org.telegram.ui.Charts.view_data; package org.telegram.ui.Charts.view_data;
import static org.telegram.messenger.AndroidUtilities.dp;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.text.Layout; import android.text.Layout;
import android.text.StaticLayout; import android.text.StaticLayout;
@ -18,7 +20,7 @@ import java.util.Locale;
public class ChartHorizontalLinesData { public class ChartHorizontalLinesData {
public int[] values; public long[] values;
public CharSequence[] valuesStr; public CharSequence[] valuesStr;
public CharSequence[] valuesStr2; public CharSequence[] valuesStr2;
private StaticLayout[] layouts; private StaticLayout[] layouts;
@ -28,15 +30,15 @@ public class ChartHorizontalLinesData {
public int fixedAlpha = 255; public int fixedAlpha = 255;
public ChartHorizontalLinesData( public ChartHorizontalLinesData(
int newMaxHeight, long newMaxHeight,
int newMinHeight, long newMinHeight,
boolean useMinHeight, boolean useMinHeight,
float k, float k,
int formatter, int formatter,
TextPaint firstTextPaint, TextPaint secondTextPaint TextPaint firstTextPaint, TextPaint secondTextPaint
) { ) {
if (!useMinHeight) { if (!useMinHeight) {
int v = newMaxHeight; long v = newMaxHeight;
if (newMaxHeight > 100) { if (newMaxHeight > 100) {
v = round(newMaxHeight); v = round(newMaxHeight);
} }
@ -45,9 +47,9 @@ public class ChartHorizontalLinesData {
int n; int n;
if (v < 6) { if (v < 6) {
n = Math.max(2, v + 1); n = (int) Math.max(2, v + 1);
} else if (v / 2 < 6) { } else if (v / 2 < 6) {
n = v / 2 + 1; n = (int) (v / 2 + 1);
if (v % 2 != 0) { if (v % 2 != 0) {
n++; n++;
} }
@ -55,7 +57,7 @@ public class ChartHorizontalLinesData {
n = 6; n = 6;
} }
values = new int[n]; values = new long[n];
valuesStr = new CharSequence[n]; valuesStr = new CharSequence[n];
layouts = new StaticLayout[n]; layouts = new StaticLayout[n];
if (k > 0) { if (k > 0) {
@ -69,7 +71,7 @@ public class ChartHorizontalLinesData {
if (k > 0) { if (k > 0) {
float v2 = (values[i] / k); float v2 = (values[i] / k);
if (skipFloatValues) { if (skipFloatValues) {
if (v2 - ((int) v2) < 0.01f) { if (v2 - ((int) v2) < 0.01f || formatter == ChartData.FORMATTER_TON) {
valuesStr2[i] = format(1, secondTextPaint, (long) v2, formatter); valuesStr2[i] = format(1, secondTextPaint, (long) v2, formatter);
} else { } else {
valuesStr2[i] = ""; valuesStr2[i] = "";
@ -81,29 +83,29 @@ public class ChartHorizontalLinesData {
} }
} else { } else {
int n; int n;
int dif = newMaxHeight - newMinHeight; long dif = newMaxHeight - newMinHeight;
float step; float step;
if (dif == 0) { if (dif == 0) {
newMinHeight--; newMinHeight--;
n = 3; n = 3;
step = 1f; step = 1f;
} else if (dif < 6) { } else if (dif < 6) {
n = Math.max(2, dif + 1); n = (int) Math.max(2, dif + 1);
step = 1f; step = 1f;
} else if (dif / 2 < 6) { } else if (dif / 2 < 6) {
n = dif / 2 + dif % 2 + 1; n = (int) (dif / 2 + dif % 2 + 1);
step = 2f; step = 2f;
} else { } else {
step = (newMaxHeight - newMinHeight) / 5f; step = (newMaxHeight - newMinHeight) / 5f;
if (step <= 0) { if (step <= 0) {
step = 1; step = 1;
n = Math.max(2, newMaxHeight - newMinHeight + 1); n = (int) (Math.max(2, newMaxHeight - newMinHeight + 1));
} else { } else {
n = 6; n = 6;
} }
} }
values = new int[n]; values = new long[n];
valuesStr = new CharSequence[n]; valuesStr = new CharSequence[n];
layouts = new StaticLayout[n]; layouts = new StaticLayout[n];
if (k > 0) { if (k > 0) {
@ -117,7 +119,7 @@ public class ChartHorizontalLinesData {
if (k > 0) { if (k > 0) {
float v = (values[i] / k); float v = (values[i] / k);
if (skipFloatValues) { if (skipFloatValues) {
if (v - ((int) v) < 0.01f) { if (v - ((int) v) < 0.01f || formatter == ChartData.FORMATTER_TON) {
valuesStr2[i] = format(1, secondTextPaint, (long) v, formatter); valuesStr2[i] = format(1, secondTextPaint, (long) v, formatter);
} else { } else {
valuesStr2[i] = ""; valuesStr2[i] = "";
@ -134,7 +136,7 @@ public class ChartHorizontalLinesData {
public CharSequence format(int a, TextPaint paint, long v, int formatter) { public CharSequence format(int a, TextPaint paint, long v, int formatter) {
if (formatter == ChartData.FORMATTER_TON) { if (formatter == ChartData.FORMATTER_TON) {
if (a == 1) { if (a == 1) {
return BillingController.getInstance().formatCurrency(v, "USD"); return "~" + BillingController.getInstance().formatCurrency(v, "USD");
} }
if (formatterTON == null) { if (formatterTON == null) {
DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.US); DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.US);
@ -145,13 +147,13 @@ public class ChartHorizontalLinesData {
formatterTON.setGroupingUsed(false); formatterTON.setGroupingUsed(false);
} }
formatterTON.setMaximumFractionDigits(v > 1_000_000_000 ? 2 : 6); formatterTON.setMaximumFractionDigits(v > 1_000_000_000 ? 2 : 6);
return ChannelMonetizationLayout.replaceTON("TON " + formatterTON.format(v / 1_000_000_000.0), paint, false); return ChannelMonetizationLayout.replaceTON("TON " + formatterTON.format(v / 1_000_000_000.0), paint, .8f, -dp(.66f), false);
} }
return AndroidUtilities.formatWholeNumber((int) v, 0); return AndroidUtilities.formatWholeNumber((int) v, 0);
} }
public static int lookupHeight(int maxValue) { public static int lookupHeight(long maxValue) {
int v = maxValue; long v = maxValue;
if (maxValue > 100) { if (maxValue > 100) {
v = round(maxValue); v = round(maxValue);
} }
@ -160,7 +162,7 @@ public class ChartHorizontalLinesData {
return step * 5; return step * 5;
} }
private static int round(int maxValue) { private static long round(long maxValue) {
float k = maxValue / 5; float k = maxValue / 5;
if (k % 10 == 0) return maxValue; if (k % 10 == 0) return maxValue;
else return ((maxValue / 10 + 1) * 10); else return ((maxValue / 10 + 1) * 10);

View file

@ -5,6 +5,11 @@ import android.animation.AnimatorListenerAdapter;
import android.content.Context; import android.content.Context;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Build; import android.os.Build;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.style.CharacterStyle;
import android.transition.ChangeBounds; import android.transition.ChangeBounds;
import android.transition.Fade; import android.transition.Fade;
import android.transition.TransitionManager; import android.transition.TransitionManager;
@ -18,6 +23,8 @@ import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.BillingController;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.R; import org.telegram.messenger.R;
import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.ChannelMonetizationLayout; import org.telegram.ui.ChannelMonetizationLayout;
@ -38,7 +45,7 @@ public class LegendSignatureView extends FrameLayout {
public boolean isTopHourChart; public boolean isTopHourChart;
LinearLayout content; LinearLayout content;
Holder[] holdes; Holder[] holders;
TextView time; TextView time;
TextView hourTime; TextView hourTime;
Drawable background; Drawable background;
@ -126,10 +133,10 @@ public class LegendSignatureView extends FrameLayout {
public void setSize(int n) { public void setSize(int n) {
content.removeAllViews(); content.removeAllViews();
holdes = new Holder[n]; holders = new Holder[n];
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
holdes[i] = new Holder(); holders[i] = new Holder();
content.addView(holdes[i].root); content.addView(holders[i].root);
} }
} }
@ -139,9 +146,10 @@ public class LegendSignatureView extends FrameLayout {
long date, long date,
ArrayList<LineViewData> lines, ArrayList<LineViewData> lines,
boolean animateChanges, boolean animateChanges,
int formatter int formatter,
float k
) { ) {
int n = holdes.length; int n = holders.length;
if (animateChanges) { if (animateChanges) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
TransitionSet transition = new TransitionSet(); TransitionSet transition = new TransitionSet();
@ -165,29 +173,34 @@ public class LegendSignatureView extends FrameLayout {
if (useHour) hourTime.setText(hourFormat.format(date)); if (useHour) hourTime.setText(hourFormat.format(date));
} }
int sum = 0; long sum = 0;
for (int i = 0; i < n; i++) { for (int i = 0; i < lines.size(); i++) {
if (lines.get(i).enabled) sum += lines.get(i).line.y[index]; if (lines.get(i).enabled) sum += lines.get(i).line.y[index];
} }
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
Holder h = holdes[i]; Holder h = holders[i];
int formatterIndex = i % 2;
LineViewData l = lines.get(formatter == ChartData.FORMATTER_TON ? i / 2 : i);
if (!lines.get(i).enabled) { if (!l.enabled) {
h.root.setVisibility(View.GONE); h.root.setVisibility(View.GONE);
} else { } else {
ChartData.Line l = lines.get(i).line;
if (h.root.getMeasuredHeight() == 0) { if (h.root.getMeasuredHeight() == 0) {
h.root.requestLayout(); h.root.requestLayout();
} }
h.root.setVisibility(View.VISIBLE); h.root.setVisibility(View.VISIBLE);
h.value.setText(formatWholeNumber(l.y[index], formatter, h.value)); h.value.setText(formatWholeNumber(l.line.y[index], formatter, formatterIndex, h.value, k));
h.signature.setText(l.name); if (formatter == ChartData.FORMATTER_TON) {
if (l.colorKey >= 0 && Theme.hasThemeKey(l.colorKey)) { h.signature.setText(LocaleController.formatString(formatterIndex == 0 ? R.string.MonetizationChartInTON : R.string.MonetizationChartInUSD, l.line.name));
h.value.setTextColor(Theme.getColor(l.colorKey, resourcesProvider));
} else { } else {
h.value.setTextColor(Theme.getCurrentTheme().isDark() ? l.colorDark : l.color); h.signature.setText(l.line.name);
}
if (l.line.colorKey >= 0 && Theme.hasThemeKey(l.line.colorKey)) {
h.value.setTextColor(Theme.getColor(l.line.colorKey, resourcesProvider));
} else {
h.value.setTextColor(Theme.getCurrentTheme().isDark() ? l.line.colorDark : l.line.color);
} }
h.signature.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); h.signature.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider));
@ -224,10 +237,10 @@ public class LegendSignatureView extends FrameLayout {
return s; return s;
} }
private DecimalFormat formatterTON; private DecimalFormat formatterTON;
public CharSequence formatWholeNumber(int v, int formatter, TextView textView) { public CharSequence formatWholeNumber(long v, int formatter, int formatterIndex, TextView textView, float k) {
if (formatter == ChartData.FORMATTER_TON) { if (formatter == ChartData.FORMATTER_TON) {
if (formatterIndex == 0) {
if (formatterTON == null) { if (formatterTON == null) {
DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.US); DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.US);
symbols.setDecimalSeparator('.'); symbols.setDecimalSeparator('.');
@ -237,7 +250,10 @@ public class LegendSignatureView extends FrameLayout {
formatterTON.setGroupingUsed(false); formatterTON.setGroupingUsed(false);
} }
formatterTON.setMaximumFractionDigits(v > 1_000_000_000 ? 2 : 6); formatterTON.setMaximumFractionDigits(v > 1_000_000_000 ? 2 : 6);
return ChannelMonetizationLayout.replaceTON("TON " + formatterTON.format(v / 1_000_000_000.), textView.getPaint(), false); return ChannelMonetizationLayout.replaceTON("TON " + formatterTON.format(v / 1_000_000_000.), textView.getPaint(), .82f, false);
} else {
return "~" + BillingController.getInstance().formatCurrency((long) (v / k), "USD");
}
} }
float num_ = v; float num_ = v;
int count = 0; int count = 0;

View file

@ -37,11 +37,11 @@ public class LineViewData {
private Theme.ResourcesProvider resourcesProvider; private Theme.ResourcesProvider resourcesProvider;
public LineViewData(ChartData.Line line) { public LineViewData(ChartData.Line line, boolean bar) {
this(line, null); this(line, bar, null);
} }
public LineViewData(ChartData.Line line, Theme.ResourcesProvider resourcesProvider) { public LineViewData(ChartData.Line line, boolean bar, Theme.ResourcesProvider resourcesProvider) {
this.resourcesProvider = resourcesProvider; this.resourcesProvider = resourcesProvider;
this.line = line; this.line = line;
@ -62,8 +62,8 @@ public class LineViewData {
selectionPaint.setColor(line.color); selectionPaint.setColor(line.color);
linesPath = new float[line.y.length << 2]; linesPath = new float[bar ? (8 * line.y.length) : line.y.length << 2];
linesPathBottom = new float[line.y.length << 2]; linesPathBottom = new float[bar ? (8 * line.y.length) : line.y.length << 2];
} }
public void updateColors() { public void updateColors() {

View file

@ -25,7 +25,7 @@ public class StackBarViewData extends LineViewData {
} }
public StackBarViewData(ChartData.Line line, Theme.ResourcesProvider resourcesProvider) { public StackBarViewData(ChartData.Line line, Theme.ResourcesProvider resourcesProvider) {
super(line); super(line, false);
this.resourcesProvider = resourcesProvider; this.resourcesProvider = resourcesProvider;
paint.setStrokeWidth(AndroidUtilities.dpf2(1)); paint.setStrokeWidth(AndroidUtilities.dpf2(1));
paint.setStyle(Paint.Style.STROKE); paint.setStyle(Paint.Style.STROKE);

View file

@ -8,7 +8,7 @@ import org.telegram.ui.Charts.data.ChartData;
public class StackLinearViewData extends LineViewData { public class StackLinearViewData extends LineViewData {
public StackLinearViewData(ChartData.Line line) { public StackLinearViewData(ChartData.Line line) {
super(line); super(line, false);
paint.setStyle(Paint.Style.FILL); paint.setStyle(Paint.Style.FILL);
if (BaseChartView.USE_LINES) { if (BaseChartView.USE_LINES) {
paint.setAntiAlias(false); paint.setAntiAlias(false);

View file

@ -7974,7 +7974,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (child instanceof ChatMessageCell) { if (child instanceof ChatMessageCell) {
ChatMessageCell messageCell = ((ChatMessageCell) child); ChatMessageCell messageCell = ((ChatMessageCell) child);
MessageObject msg = messageCell.getPrimaryMessageObject(); MessageObject msg = messageCell.getPrimaryMessageObject();
if (msg.messageOwner != null && msg.messageOwner.via_business_bot_id != 0) { if (msg != null && msg.messageOwner != null && msg.messageOwner.via_business_bot_id != 0) {
cell = messageCell; cell = messageCell;
} }
} }
@ -27952,7 +27952,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
popupLayout.addView(rateTranscriptionLayout, rateTranscriptionLayoutParams); popupLayout.addView(rateTranscriptionLayout, rateTranscriptionLayoutParams);
} }
if (selectedObject != null && selectedObject.isSponsored() && !selectedObject.sponsoredCanReport) { if (selectedObject != null && selectedObject.isSponsored()) {
if (selectedObject.sponsoredInfo != null || selectedObject.sponsoredAdditionalInfo != null || selectedObject.sponsoredWebPage != null) { if (selectedObject.sponsoredInfo != null || selectedObject.sponsoredAdditionalInfo != null || selectedObject.sponsoredWebPage != null) {
LinearLayout linearLayout = new LinearLayout(getParentActivity()); LinearLayout linearLayout = new LinearLayout(getParentActivity());
linearLayout.setOrientation(LinearLayout.VERTICAL); linearLayout.setOrientation(LinearLayout.VERTICAL);
@ -28043,7 +28043,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
final int foregroundIndex = popupLayout.addViewToSwipeBack(linearLayout); final int foregroundIndex = popupLayout.addViewToSwipeBack(linearLayout);
ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getParentActivity(), true, true, themeDelegate); ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getParentActivity(), true, true, themeDelegate);
cell.setTextAndIcon(LocaleController.getString("SponsoredMessageSponsor", R.string.SponsoredMessageSponsor), R.drawable.msg_channel); cell.setTextAndIcon(LocaleController.getString(selectedObject.sponsoredCanReport ? R.string.SponsoredMessageSponsorReportable : R.string.SponsoredMessageSponsor), R.drawable.msg_channel);
popupLayout.addView(cell); popupLayout.addView(cell);
cell.setOnClickListener(v1 -> { cell.setOnClickListener(v1 -> {
if (contentView == null || getParentActivity() == null) { if (contentView == null || getParentActivity() == null) {
@ -28053,7 +28053,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}); });
popupLayout.addView(new ActionBarPopupWindow.GapView(contentView.getContext(), themeDelegate), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); popupLayout.addView(new ActionBarPopupWindow.GapView(contentView.getContext(), themeDelegate), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8));
} }
if (!selectedObject.sponsoredCanReport) {
FrameLayout sponsoredAbout = new FrameLayout(getParentActivity()) { FrameLayout sponsoredAbout = new FrameLayout(getParentActivity()) {
@Override @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
@ -28105,6 +28105,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}); });
popupLayout.addView(new ActionBarPopupWindow.GapView(contentView.getContext(), themeDelegate), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); popupLayout.addView(new ActionBarPopupWindow.GapView(contentView.getContext(), themeDelegate), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8));
} }
}
scrimPopupWindowItems = new ActionBarMenuSubItem[items.size()]; scrimPopupWindowItems = new ActionBarMenuSubItem[items.size()];
for (int a = 0, N = items.size(); a < N; a++) { for (int a = 0, N = items.size(); a < N; a++) {
ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getParentActivity(), a == 0, a == N - 1, themeDelegate); ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getParentActivity(), a == 0, a == N - 1, themeDelegate);

View file

@ -2530,6 +2530,7 @@ public class AlertsCreator {
if (users.isEmpty()) if (users.isEmpty())
return; return;
AndroidUtilities.runOnUIThread(() -> { AndroidUtilities.runOnUIThread(() -> {
if (!LaunchActivity.isActive) return;
BaseFragment lastFragment = LaunchActivity.getLastFragment(); BaseFragment lastFragment = LaunchActivity.getLastFragment();
if (lastFragment != null && lastFragment.getParentActivity() != null) { if (lastFragment != null && lastFragment.getParentActivity() != null) {
LimitReachedBottomSheet restrictedUsersBottomSheet = new LimitReachedBottomSheet(lastFragment, lastFragment.getParentActivity(), LimitReachedBottomSheet.TYPE_ADD_MEMBERS_RESTRICTED, currentAccount, null); LimitReachedBottomSheet restrictedUsersBottomSheet = new LimitReachedBottomSheet(lastFragment, lastFragment.getParentActivity(), LimitReachedBottomSheet.TYPE_ADD_MEMBERS_RESTRICTED, currentAccount, null);

View file

@ -3705,6 +3705,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
} }
new File(audioToSendPath).delete(); new File(audioToSendPath).delete();
} }
MediaController.getInstance().cleanRecording(true);
MediaDataController.getInstance(currentAccount).pushDraftVoiceMessage(dialog_id, parentFragment != null && parentFragment.isTopic ? parentFragment.getTopicId() : 0, null); MediaDataController.getInstance(currentAccount).pushDraftVoiceMessage(dialog_id, parentFragment != null && parentFragment.isTopic ? parentFragment.getTopicId() : 0, null);
MediaController.getInstance().stopRecording(0, false, 0, false); MediaController.getInstance().stopRecording(0, false, 0, false);
millisecondsRecorded = 0; millisecondsRecorded = 0;
@ -6432,6 +6433,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
if (playing != null && playing == audioToSendMessageObject) { if (playing != null && playing == audioToSendMessageObject) {
MediaController.getInstance().cleanupPlayer(true, true); MediaController.getInstance().cleanupPlayer(true, true);
} }
MediaController.getInstance().cleanRecording(false);
MediaDataController.getInstance(currentAccount).pushDraftVoiceMessage(dialog_id, parentFragment != null && parentFragment.isTopic ? parentFragment.getTopicId() : 0, null); MediaDataController.getInstance(currentAccount).pushDraftVoiceMessage(dialog_id, parentFragment != null && parentFragment.isTopic ? parentFragment.getTopicId() : 0, null);
SendMessagesHelper.SendMessageParams params = SendMessagesHelper.SendMessageParams.of(audioToSend, null, audioToSendPath, dialog_id, replyingMessageObject, getThreadMessage(), null, null, null, null, notify, scheduleDate, voiceOnce ? 0x7FFFFFFF : 0, null, null, false); SendMessagesHelper.SendMessageParams params = SendMessagesHelper.SendMessageParams.of(audioToSend, null, audioToSendPath, dialog_id, replyingMessageObject, getThreadMessage(), null, null, null, null, notify, scheduleDate, voiceOnce ? 0x7FFFFFFF : 0, null, null, false);
params.quick_reply_shortcut = parentFragment != null ? parentFragment.quickReplyShortcut : null; params.quick_reply_shortcut = parentFragment != null ? parentFragment.quickReplyShortcut : null;
@ -9064,7 +9066,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
controlsView.periodDrawable.setValue(1, voiceOnce, true); controlsView.periodDrawable.setValue(1, voiceOnce, true);
} }
TL_stories.StoryItem storyItem = delegate != null ? delegate.getReplyToStory() : null; TL_stories.StoryItem storyItem = delegate != null ? delegate.getReplyToStory() : null;
MediaController.getInstance().prepareResumedRecording(currentAccount, draft, dialog_id, replyingMessageObject, getThreadMessage(), storyItem, recordingGuid, true, parentFragment != null ? parentFragment.quickReplyShortcut : null, parentFragment != null ? parentFragment.getQuickReplyId() : 0); MediaController.getInstance().prepareResumedRecording(currentAccount, draft, dialog_id, replyingMessageObject, getThreadMessage(), storyItem, recordingGuid, parentFragment != null ? parentFragment.quickReplyShortcut : null, parentFragment != null ? parentFragment.getQuickReplyId() : 0);
} }
public void setSelection(int start) { public void setSelection(int start) {

View file

@ -60,6 +60,19 @@ public class ColoredImageSpan extends ReplacementSpan {
this.verticalAlignment = verticalAlignment; this.verticalAlignment = verticalAlignment;
} }
private boolean isRelativeSize;
private Paint.FontMetricsInt fontMetrics;
public void setRelativeSize(Paint.FontMetricsInt fontMetricsInt) {
this.isRelativeSize = true;
this.fontMetrics = fontMetricsInt;
if (fontMetrics != null) {
setSize(Math.abs(fontMetrics.descent) + Math.abs(fontMetrics.ascent));
if (size == 0) {
setSize(AndroidUtilities.dp(20));
}
}
}
public void setSize(int size) { public void setSize(int size) {
this.size = size; this.size = size;
drawable.setBounds(0, 0, size, size); drawable.setBounds(0, 0, size, size);
@ -83,7 +96,20 @@ public class ColoredImageSpan extends ReplacementSpan {
} }
@Override @Override
public int getSize(@NonNull Paint paint, CharSequence charSequence, int i, int i1, @Nullable Paint.FontMetricsInt fontMetricsInt) { public int getSize(@NonNull Paint paint, CharSequence charSequence, int i, int i1, @Nullable Paint.FontMetricsInt fm) {
if (isRelativeSize && fontMetrics != null) {
if (fm == null) {
fm = new Paint.FontMetricsInt();
}
if (fm != null) {
fm.ascent = fontMetrics.ascent;
fm.descent = fontMetrics.descent;
fm.top = fontMetrics.top;
fm.bottom = fontMetrics.bottom;
}
return (int) (scaleX * Math.abs(spaceScaleX) * size);
}
if (sizeWidth != 0) if (sizeWidth != 0)
return (int) (Math.abs(scaleX) * sizeWidth); return (int) (Math.abs(scaleX) * sizeWidth);
return (int) (Math.abs(scaleX) * Math.abs(spaceScaleX) * (size != 0 ? size : drawable.getIntrinsicWidth())); return (int) (Math.abs(scaleX) * Math.abs(spaceScaleX) * (size != 0 ? size : drawable.getIntrinsicWidth()));

View file

@ -149,7 +149,7 @@ public class GroupCreateSpan extends View {
case "premium": case "premium":
isFlag = true; isFlag = true;
avatarDrawable.setColor(Theme.getColor(Theme.key_premiumGradientBackground2, resourcesProvider)); avatarDrawable.setColor(Theme.getColor(Theme.key_premiumGradientBackground2, resourcesProvider));
firstName = "Premium Users"; firstName = LocaleController.getString(R.string.PrivacyPremium);
break; break;
case "archived": case "archived":
default: default:

View file

@ -26,6 +26,7 @@ import android.widget.TextView;
import androidx.core.graphics.ColorUtils; import androidx.core.graphics.ColorUtils;
import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.LiteMode; import org.telegram.messenger.LiteMode;
import org.telegram.messenger.SharedConfig; import org.telegram.messenger.SharedConfig;
import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.SimpleTextView;
@ -498,7 +499,7 @@ public class LinkSpanDrawable<S extends CharacterStyle> {
} }
private boolean isCustomLinkCollector; private boolean isCustomLinkCollector;
private LinkCollector links; private final LinkCollector links;
private Theme.ResourcesProvider resourcesProvider; private Theme.ResourcesProvider resourcesProvider;
AnimatedEmojiSpan.EmojiGroupedSpans stack; AnimatedEmojiSpan.EmojiGroupedSpans stack;
@ -646,6 +647,8 @@ public class LinkSpanDrawable<S extends CharacterStyle> {
return pressedLink != null || super.onTouchEvent(event); return pressedLink != null || super.onTouchEvent(event);
} }
private boolean loggedError = false;
@Override @Override
protected void onDraw(Canvas canvas) { protected void onDraw(Canvas canvas) {
if (!isCustomLinkCollector) { if (!isCustomLinkCollector) {
@ -653,21 +656,29 @@ public class LinkSpanDrawable<S extends CharacterStyle> {
if (!disablePaddingsOffset) { if (!disablePaddingsOffset) {
canvas.translate(disablePaddingsOffsetX ? 0 : getPaddingLeft(), disablePaddingsOffsetY ? 0 : getPaddingTop()); canvas.translate(disablePaddingsOffsetX ? 0 : getPaddingLeft(), disablePaddingsOffsetY ? 0 : getPaddingTop());
} }
if (links.draw(canvas)) { if (links != null && links.draw(canvas)) {
invalidate(); invalidate();
} }
canvas.restore(); canvas.restore();
} }
super.onDraw(canvas); boolean restore = false;
float offset = (getGravity() & Gravity.CENTER_VERTICAL) != 0 && getLayout() != null ? getPaddingTop() + (getHeight() - getPaddingTop() - getPaddingBottom() - getLayout().getHeight()) / 2f : 0; try {
Layout layout = getLayout();
float offset = (getGravity() & Gravity.CENTER_VERTICAL) != 0 && layout != null ? getPaddingTop() + (getHeight() - getPaddingTop() - getPaddingBottom() - layout.getHeight()) / 2f : 0;
if (offset != 0 || getPaddingLeft() != 0) { if (offset != 0 || getPaddingLeft() != 0) {
canvas.save(); canvas.save();
restore = true;
canvas.translate(getPaddingLeft(), offset); canvas.translate(getPaddingLeft(), offset);
} }
AnimatedEmojiSpan.drawAnimatedEmojis(canvas, getLayout(), stack, 0, null, 0, 0, 0, 1f); AnimatedEmojiSpan.drawAnimatedEmojis(canvas, layout, stack, 0, null, 0, 0, 0, 1f);
if (offset != 0 || getPaddingLeft() != 0) { } catch (Exception e) {
if (!loggedError) FileLog.e(e, true);
loggedError = true;
}
if (restore) {
canvas.restore(); canvas.restore();
} }
super.onDraw(canvas);
} }
@Override @Override

View file

@ -2032,7 +2032,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh
return; return;
} }
if (editingText) { if (editingText && currentEntityView != null) {
selectEntity(null); selectEntity(null);
return; return;
} }

View file

@ -16,13 +16,11 @@ import android.graphics.Matrix;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Path; import android.graphics.Path;
import android.graphics.PathMeasure; import android.graphics.PathMeasure;
import android.graphics.PointF;
import android.graphics.PorterDuff; import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode; import android.graphics.PorterDuffXfermode;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.RectF; import android.graphics.RectF;
import android.os.Build; import android.os.Build;
import android.util.Log;
import android.util.TypedValue; import android.util.TypedValue;
import android.view.Gravity; import android.view.Gravity;
import android.view.MotionEvent; import android.view.MotionEvent;
@ -33,7 +31,6 @@ import android.widget.FrameLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.graphics.ColorUtils;
import com.google.mlkit.common.MlKitException; import com.google.mlkit.common.MlKitException;
import com.google.mlkit.vision.common.InputImage; import com.google.mlkit.vision.common.InputImage;
@ -806,8 +803,10 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter.
sourceBitmap = null; sourceBitmap = null;
if (objects != null) { if (objects != null) {
for (int i = 0; i < objects.length; ++i) { for (int i = 0; i < objects.length; ++i) {
if (objects[i] != null) {
objects[i].recycle(); objects[i].recycle();
} }
}
objects = null; objects = null;
} }
segmentingLoaded = false; segmentingLoaded = false;

View file

@ -1264,6 +1264,17 @@ public class ReactionsLayoutInBubble {
return false; return false;
} }
public VisibleReaction flatten() {
if (documentId != 0) {
TLRPC.Document document = AnimatedEmojiDrawable.findDocument(UserConfig.selectedAccount, documentId);
String emoji = MessageObject.findAnimatedEmojiEmoticon(document, null);
if (emoji != null) {
return VisibleReaction.fromEmojicon(emoji);
}
}
return this;
}
@NonNull @NonNull
@Override @Override
public String toString() { public String toString() {

View file

@ -174,6 +174,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
RectF rectF = new RectF(); RectF rectF = new RectF();
HashSet<ReactionsLayoutInBubble.VisibleReaction> selectedReactions = new HashSet<>(); HashSet<ReactionsLayoutInBubble.VisibleReaction> selectedReactions = new HashSet<>();
HashSet<ReactionsLayoutInBubble.VisibleReaction> alwaysSelectedReactions = new HashSet<>();
private int[] location = new int[2]; private int[] location = new int[2];
@ -1250,12 +1251,20 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
selectedReactions.clear(); selectedReactions.clear();
selectedReactions.addAll(getInclusiveReactions(messages)); selectedReactions.addAll(getInclusiveReactions(messages));
updateSelected(); updateSelected();
if (type == TYPE_STICKER_SET_EMOJI) {
alwaysSelectedReactions.addAll(selectedReactions);
setMessage(messageObject, null);
}
} }
public void setSelectedReactionInclusive(ReactionsLayoutInBubble.VisibleReaction visibleReaction) { public void setSelectedReactionInclusive(ReactionsLayoutInBubble.VisibleReaction visibleReaction) {
selectedReactions.clear(); selectedReactions.clear();
selectedReactions.add(visibleReaction); selectedReactions.add(visibleReaction);
updateSelected(); updateSelected();
if (type == TYPE_STICKER_SET_EMOJI) {
alwaysSelectedReactions.addAll(selectedReactions);
setMessage(messageObject, null);
}
} }
private void updateSelected() { private void updateSelected() {
@ -1280,11 +1289,20 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
} }
private void fillRecentReactionsList(List<ReactionsLayoutInBubble.VisibleReaction> visibleReactions) { private void fillRecentReactionsList(List<ReactionsLayoutInBubble.VisibleReaction> visibleReactions) {
HashSet<ReactionsLayoutInBubble.VisibleReaction> hashSet = new HashSet<>();
int added = 0;
if (type == TYPE_STICKER_SET_EMOJI) {
for (ReactionsLayoutInBubble.VisibleReaction visibleReaction : alwaysSelectedReactions) {
if (!hashSet.contains(visibleReaction)) {
hashSet.add(visibleReaction);
visibleReactions.add(visibleReaction);
added++;
}
}
}
if (!allReactionsAvailable || type == TYPE_STICKER_SET_EMOJI) { if (!allReactionsAvailable || type == TYPE_STICKER_SET_EMOJI) {
if (type == TYPE_TAGS) { if (type == TYPE_TAGS) {
ArrayList<TLRPC.Reaction> topReactions = MediaDataController.getInstance(currentAccount).getSavedReactions(); ArrayList<TLRPC.Reaction> topReactions = MediaDataController.getInstance(currentAccount).getSavedReactions();
HashSet<ReactionsLayoutInBubble.VisibleReaction> hashSet = new HashSet<>();
int added = 0;
for (int i = 0; i < topReactions.size(); i++) { for (int i = 0; i < topReactions.size(); i++) {
ReactionsLayoutInBubble.VisibleReaction visibleReaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(topReactions.get(i)); ReactionsLayoutInBubble.VisibleReaction visibleReaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(topReactions.get(i));
if (!hashSet.contains(visibleReaction)) { if (!hashSet.contains(visibleReaction)) {
@ -1313,8 +1331,6 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
} else { } else {
topReactions = MediaDataController.getInstance(currentAccount).getTopReactions(); topReactions = MediaDataController.getInstance(currentAccount).getTopReactions();
} }
HashSet<ReactionsLayoutInBubble.VisibleReaction> hashSet = new HashSet<>();
int added = 0;
if (type == TYPE_TAGS) { if (type == TYPE_TAGS) {
TLRPC.TL_messages_savedReactionsTags savedTags = MessagesController.getInstance(currentAccount).getSavedReactionTags(0); TLRPC.TL_messages_savedReactionsTags savedTags = MessagesController.getInstance(currentAccount).getSavedReactionTags(0);
if (savedTags != null) { if (savedTags != null) {

View file

@ -1618,7 +1618,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
} }
searchItem.setVisibility(View.GONE); searchItem.setVisibility(View.GONE);
searchWas = text.length() != 0 || searchingReaction != null; searchWas = text.length() != 0 || searchingReaction != null;
switchToCurrentSelectedMode(false); post(() -> switchToCurrentSelectedMode(false));
if (mediaPages[0].selectedType == TAB_FILES) { if (mediaPages[0].selectedType == TAB_FILES) {
if (documentsSearchAdapter == null) { if (documentsSearchAdapter == null) {
return; return;

View file

@ -1099,7 +1099,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not
private void checkOptions() { private void checkOptions() {
final MediaDataController mediaDataController = MediaDataController.getInstance(currentAccount); final MediaDataController mediaDataController = MediaDataController.getInstance(currentAccount);
boolean notInstalled = !mediaDataController.isStickerPackInstalled(stickerSet.set.id); boolean notInstalled = stickerSet == null || !mediaDataController.isStickerPackInstalled(stickerSet.set.id);
if (stickerSet != null && stickerSet.set != null && stickerSet.set.creator && deleteItem == null && !DISABLE_STICKER_EDITOR) { if (stickerSet != null && stickerSet.set != null && stickerSet.set.creator && deleteItem == null && !DISABLE_STICKER_EDITOR) {
optionsButton.addSubItem(3, R.drawable.tabs_reorder, LocaleController.getString(R.string.StickersReorder)); optionsButton.addSubItem(3, R.drawable.tabs_reorder, LocaleController.getString(R.string.StickersReorder));
optionsButton.addSubItem(4, R.drawable.msg_edit, LocaleController.getString(R.string.EditName)); optionsButton.addSubItem(4, R.drawable.msg_edit, LocaleController.getString(R.string.EditName));
@ -2156,6 +2156,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not
} else { } else {
if (holder.getItemViewType() != TYPE_ADD_STICKER) { if (holder.getItemViewType() != TYPE_ADD_STICKER) {
StickerEmojiCell cell = (StickerEmojiCell) holder.itemView; StickerEmojiCell cell = (StickerEmojiCell) holder.itemView;
if (stickerSet == null) return;
cell.setSticker(stickerSet.documents.get(position), null, stickerSet, null, showEmoji, isEditModeEnabled); cell.setSticker(stickerSet.documents.get(position), null, stickerSet, null, showEmoji, isEditModeEnabled);
cell.editModeIcon.setOnClickListener(v -> { cell.editModeIcon.setOnClickListener(v -> {
ContentPreviewViewer.getInstance().showMenuFor(cell); ContentPreviewViewer.getInstance().showMenuFor(cell);

View file

@ -257,7 +257,7 @@ public class UItem extends AdapterWithDiffUtils.Item {
} }
public static UItem asChart(int type, int stats_dc, StatisticActivity.ChartViewData data) { public static UItem asChart(int type, int stats_dc, StatisticActivity.ChartViewData data) {
UItem item = new UItem(UniversalAdapter.VIEW_TYPE_CHART0 + type, false); UItem item = new UItem(UniversalAdapter.VIEW_TYPE_CHART_LINEAR + type, false);
item.intValue = stats_dc; item.intValue = stats_dc;
item.object = data; item.object = data;
return item; return item;

View file

@ -64,21 +64,23 @@ public class UniversalAdapter extends AdapterWithDiffUtils {
public static final int VIEW_TYPE_QUICK_REPLY = 16; public static final int VIEW_TYPE_QUICK_REPLY = 16;
public static final int VIEW_TYPE_LARGE_QUICK_REPLY = 17; public static final int VIEW_TYPE_LARGE_QUICK_REPLY = 17;
public static final int VIEW_TYPE_CHART0 = 18; public static final int VIEW_TYPE_CHART_LINEAR = 18;
public static final int VIEW_TYPE_CHART1 = 19; public static final int VIEW_TYPE_CHART_DOUBLE_LINEAR = 19;
public static final int VIEW_TYPE_CHART2 = 20; public static final int VIEW_TYPE_CHART_STACK_BAR = 20;
public static final int VIEW_TYPE_CHART3 = 21; public static final int VIEW_TYPE_CHART_BAR = 21;
public static final int VIEW_TYPE_CHART_STACK_LINEAR = 22;
public static final int VIEW_TYPE_CHART_LINEAR_BAR = 23;
public static final int VIEW_TYPE_PROCEED_OVERVIEW = 22; public static final int VIEW_TYPE_PROCEED_OVERVIEW = 24;
public static final int VIEW_TYPE_TRANSACTION = 23; public static final int VIEW_TYPE_TRANSACTION = 25;
public static final int VIEW_TYPE_LARGE_HEADER = 24; public static final int VIEW_TYPE_LARGE_HEADER = 26;
public static final int VIEW_TYPE_RADIO_USER = 25; public static final int VIEW_TYPE_RADIO_USER = 27;
public static final int VIEW_TYPE_SPACE = 26; public static final int VIEW_TYPE_SPACE = 28;
public static final int VIEW_TYPE_BUSINESS_LINK = 27; public static final int VIEW_TYPE_BUSINESS_LINK = 29;
public static final int VIEW_TYPE_RIGHT_ICON_TEXT = 28; public static final int VIEW_TYPE_RIGHT_ICON_TEXT = 30;
private final RecyclerListView listView; private final RecyclerListView listView;
private final Context context; private final Context context;
@ -319,14 +321,16 @@ public class UniversalAdapter extends AdapterWithDiffUtils {
view = new QuickRepliesActivity.LargeQuickReplyView(context, resourcesProvider); view = new QuickRepliesActivity.LargeQuickReplyView(context, resourcesProvider);
view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite));
break; break;
case VIEW_TYPE_CHART0: case VIEW_TYPE_CHART_LINEAR:
case VIEW_TYPE_CHART1: case VIEW_TYPE_CHART_DOUBLE_LINEAR:
case VIEW_TYPE_CHART2: case VIEW_TYPE_CHART_STACK_BAR:
case VIEW_TYPE_CHART3: case VIEW_TYPE_CHART_BAR:
case VIEW_TYPE_CHART_STACK_LINEAR:
case VIEW_TYPE_CHART_LINEAR_BAR:
if (chartSharedUI == null) { if (chartSharedUI == null) {
chartSharedUI = new BaseChartView.SharedUiComponents(); chartSharedUI = new BaseChartView.SharedUiComponents();
} }
view = new StatisticActivity.UniversalChartCell(context, currentAccount, viewType - VIEW_TYPE_CHART0, chartSharedUI, classGuid); view = new StatisticActivity.UniversalChartCell(context, currentAccount, viewType - VIEW_TYPE_CHART_LINEAR, chartSharedUI, classGuid);
view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite));
break; break;
case VIEW_TYPE_TRANSACTION: case VIEW_TYPE_TRANSACTION:
@ -554,10 +558,12 @@ public class UniversalAdapter extends AdapterWithDiffUtils {
replyView2.set((QuickRepliesController.QuickReply) item.object, divider); replyView2.set((QuickRepliesController.QuickReply) item.object, divider);
} }
break; break;
case VIEW_TYPE_CHART0: case VIEW_TYPE_CHART_LINEAR:
case VIEW_TYPE_CHART1: case VIEW_TYPE_CHART_DOUBLE_LINEAR:
case VIEW_TYPE_CHART2: case VIEW_TYPE_CHART_STACK_BAR:
case VIEW_TYPE_CHART3: case VIEW_TYPE_CHART_BAR:
case VIEW_TYPE_CHART_STACK_LINEAR:
case VIEW_TYPE_CHART_LINEAR_BAR:
((StatisticActivity.UniversalChartCell) holder.itemView).set( ((StatisticActivity.UniversalChartCell) holder.itemView).set(
item.intValue, item.intValue,
(StatisticActivity.ChartViewData) item.object, (StatisticActivity.ChartViewData) item.object,

View file

@ -12304,6 +12304,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
fragmentView.requestLayout(); fragmentView.requestLayout();
} }
} else { } else {
if (viewPages != null) {
for (int i = 0; i < viewPages.length; i++) { for (int i = 0; i < viewPages.length; i++) {
ViewPage page = viewPages[i]; ViewPage page = viewPages[i];
if (page != null) { if (page != null) {
@ -12313,6 +12314,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
page.listView.setClipChildren(true); page.listView.setClipChildren(true);
} }
} }
}
if (actionBar != null) { if (actionBar != null) {
actionBar.setLayerType(View.LAYER_TYPE_NONE, null); actionBar.setLayerType(View.LAYER_TYPE_NONE, null);
} }

View file

@ -213,6 +213,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
public final static String EXTRA_FORCE_NOT_INTERNAL_APPS = "force_not_internal_apps"; public final static String EXTRA_FORCE_NOT_INTERNAL_APPS = "force_not_internal_apps";
public final static Pattern PREFIX_T_ME_PATTERN = Pattern.compile("^(?:http(?:s|)://|)([A-z0-9-]+?)\\.t\\.me"); public final static Pattern PREFIX_T_ME_PATTERN = Pattern.compile("^(?:http(?:s|)://|)([A-z0-9-]+?)\\.t\\.me");
public static boolean isActive;
public static boolean isResumed; public static boolean isResumed;
public static Runnable onResumeStaticCallback; public static Runnable onResumeStaticCallback;
@ -329,6 +330,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
isActive = true;
if (BuildVars.DEBUG_VERSION) { if (BuildVars.DEBUG_VERSION) {
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder(StrictMode.getVmPolicy()) StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder(StrictMode.getVmPolicy())
.detectLeakedClosableObjects() .detectLeakedClosableObjects()
@ -4964,6 +4966,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
AtomicBoolean allowWrite = new AtomicBoolean(); AtomicBoolean allowWrite = new AtomicBoolean();
BaseFragment lastFragment = mainFragmentsStack.get(mainFragmentsStack.size() - 1); BaseFragment lastFragment = mainFragmentsStack.get(mainFragmentsStack.size() - 1);
Runnable loadBotSheet = () -> { Runnable loadBotSheet = () -> {
if (!isActive) return;
BotWebViewSheet sheet = new BotWebViewSheet(LaunchActivity.this, lastFragment.getResourceProvider()); BotWebViewSheet sheet = new BotWebViewSheet(LaunchActivity.this, lastFragment.getResourceProvider());
sheet.setParentActivity(LaunchActivity.this); sheet.setParentActivity(LaunchActivity.this);
sheet.requestWebView(intentAccount, user.id, user.id, null, null, BotWebViewSheet.TYPE_WEB_VIEW_BOT_APP, 0, false, lastFragment, botApp.app, allowWrite.get(), botAppStartParam, user); sheet.requestWebView(intentAccount, user.id, user.id, null, null, BotWebViewSheet.TYPE_WEB_VIEW_BOT_APP, 0, false, lastFragment, botApp.app, allowWrite.get(), botAppStartParam, user);
@ -6007,6 +6010,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
@Override @Override
protected void onDestroy() { protected void onDestroy() {
isActive = false;
if (PhotoViewer.getPipInstance() != null) { if (PhotoViewer.getPipInstance() != null) {
PhotoViewer.getPipInstance().destroyPhotoViewer(); PhotoViewer.getPipInstance().destroyPhotoViewer();
} }

View file

@ -6625,7 +6625,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
return; return;
} }
Runnable onEnd = () -> { Runnable onEnd = () -> {
cropTransform.setViewTransform(previousHasTransform, previousCropPx, previousCropPy, previousCropRotation, previousCropOrientation, previousCropScale, 1.0f, 1.0f, previousCropPw, previousCropPh, 0, 0, previousCropMirrored); cropTransform.setViewTransform(previousHasTransform, previousCropPx, previousCropPy, previousCropRotation, previousCropOrientation, previousCropScale, scale1(), scale1(), previousCropPw, previousCropPh, 0, 0, previousCropMirrored);
// if (previousHasTransform) { // if (previousHasTransform) {
// editState.cropState = new MediaController.CropState(); // editState.cropState = new MediaController.CropState();
// editState.cropState.cropPx = previousCropPx; // editState.cropState.cropPx = previousCropPx;

View file

@ -1587,7 +1587,7 @@ public class PrivacyControlActivity extends BaseFragment implements Notification
} else if (rulesType == PRIVACY_RULES_TYPE_MESSAGES) { } else if (rulesType == PRIVACY_RULES_TYPE_MESSAGES) {
headerCell.setText(LocaleController.getString(R.string.PrivacyMessagesTitle)); headerCell.setText(LocaleController.getString(R.string.PrivacyMessagesTitle));
} else if (rulesType == PRIVACY_RULES_TYPE_BIRTHDAY) { } else if (rulesType == PRIVACY_RULES_TYPE_BIRTHDAY) {
headerCell.setText(LocaleController.getString(R.string.PrivacyBirthday)); headerCell.setText(LocaleController.getString(R.string.PrivacyBirthdayTitle));
} else { } else {
headerCell.setText(LocaleController.getString("LastSeenTitle", R.string.LastSeenTitle)); headerCell.setText(LocaleController.getString("LastSeenTitle", R.string.LastSeenTitle));
} }

View file

@ -1856,6 +1856,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
getNotificationCenter().addObserver(this, NotificationCenter.reloadDialogPhotos); getNotificationCenter().addObserver(this, NotificationCenter.reloadDialogPhotos);
getNotificationCenter().addObserver(this, NotificationCenter.storiesUpdated); getNotificationCenter().addObserver(this, NotificationCenter.storiesUpdated);
getNotificationCenter().addObserver(this, NotificationCenter.storiesReadUpdated); getNotificationCenter().addObserver(this, NotificationCenter.storiesReadUpdated);
getNotificationCenter().addObserver(this, NotificationCenter.userIsPremiumBlockedUpadted);
NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded);
updateRowsIds(); updateRowsIds();
if (listAdapter != null) { if (listAdapter != null) {
@ -1927,6 +1928,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
getNotificationCenter().removeObserver(this, NotificationCenter.reloadDialogPhotos); getNotificationCenter().removeObserver(this, NotificationCenter.reloadDialogPhotos);
getNotificationCenter().removeObserver(this, NotificationCenter.storiesUpdated); getNotificationCenter().removeObserver(this, NotificationCenter.storiesUpdated);
getNotificationCenter().removeObserver(this, NotificationCenter.storiesReadUpdated); getNotificationCenter().removeObserver(this, NotificationCenter.storiesReadUpdated);
getNotificationCenter().removeObserver(this, NotificationCenter.userIsPremiumBlockedUpadted);
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded);
if (avatarsViewPager != null) { if (avatarsViewPager != null) {
avatarsViewPager.onDestroy(); avatarsViewPager.onDestroy();
@ -7396,6 +7398,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
avatarImage.setHasStories(needInsetForStories()); avatarImage.setHasStories(needInsetForStories());
updateAvatarRoundRadius(); updateAvatarRoundRadius();
} }
} else if (id == NotificationCenter.userIsPremiumBlockedUpadted) {
if (otherItem != null) {
otherItem.setSubItemShown(start_secret_chat, !getMessagesController().isUserPremiumBlocked(userId));
}
} }
} }
@ -8112,6 +8118,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
if (birthdayFetcher != null) { if (birthdayFetcher != null) {
birthdayFetcher.subscribe(this::createBirthdayEffect); birthdayFetcher.subscribe(this::createBirthdayEffect);
} }
if (otherItem != null) {
otherItem.setSubItemShown(start_secret_chat, !getMessagesController().isUserPremiumBlocked(userId));
}
} }
public boolean canSearchMembers() { public boolean canSearchMembers() {
@ -9408,6 +9417,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
otherItem.addSubItem(gift_premium, R.drawable.msg_gift_premium, LocaleController.getString(R.string.GiftPremium)); otherItem.addSubItem(gift_premium, R.drawable.msg_gift_premium, LocaleController.getString(R.string.GiftPremium));
} }
otherItem.addSubItem(start_secret_chat, R.drawable.msg_secret, LocaleController.getString("StartEncryptedChat", R.string.StartEncryptedChat)); otherItem.addSubItem(start_secret_chat, R.drawable.msg_secret, LocaleController.getString("StartEncryptedChat", R.string.StartEncryptedChat));
otherItem.setSubItemShown(start_secret_chat, !getMessagesController().isUserPremiumBlocked(userId));
} }
if (!isBot && getContactsController().contactsDict.get(userId) != null) { if (!isBot && getContactsController().contactsDict.get(userId) != null) {
otherItem.addSubItem(add_shortcut, R.drawable.msg_home, LocaleController.getString("AddShortcut", R.string.AddShortcut)); otherItem.addSubItem(add_shortcut, R.drawable.msg_home, LocaleController.getString("AddShortcut", R.string.AddShortcut));

View file

@ -106,8 +106,8 @@ public class RevenueSharingAdsInfoBottomSheet extends BottomSheet {
textViewDescription4.setTextAlignment(TextView.TEXT_ALIGNMENT_CENTER); textViewDescription4.setTextAlignment(TextView.TEXT_ALIGNMENT_CENTER);
linearLayout.addView(textViewDescription4, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 22, 0, 22, 0)); linearLayout.addView(textViewDescription4, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 22, 0, 22, 0));
SpannableStringBuilder bottomSubtitle1 = AndroidUtilities.replaceTags(LocaleController.getString("RevenueSharingAdsInfo4Subtitle", R.string.RevenueSharingAdsInfo4Subtitle)); SpannableStringBuilder bottomSubtitle1 = AndroidUtilities.replaceTags(LocaleController.getString(R.string.RevenueSharingAdsInfo4Subtitle2));
String bottomSubtitle2 = getString("RevenueSharingAdsInfo4Subtitle", R.string.RevenueSharingAdsInfo4SubtitleLearnMore); String bottomSubtitle2 = getString(R.string.RevenueSharingAdsInfo4SubtitleLearnMore);
SpannableStringBuilder stringBuilder2 = AndroidUtilities.replaceSingleTag(bottomSubtitle2, Theme.key_chat_messageLinkIn, 0, () -> Browser.openUrl(getContext(), LocaleController.getString("PromoteUrl", R.string.PromoteUrl))); SpannableStringBuilder stringBuilder2 = AndroidUtilities.replaceSingleTag(bottomSubtitle2, Theme.key_chat_messageLinkIn, 0, () -> Browser.openUrl(getContext(), LocaleController.getString("PromoteUrl", R.string.PromoteUrl)));
SpannableString arrowStr = new SpannableString(">"); SpannableString arrowStr = new SpannableString(">");
ColoredImageSpan span = new ColoredImageSpan(R.drawable.attach_arrow_right); ColoredImageSpan span = new ColoredImageSpan(R.drawable.attach_arrow_right);
@ -133,7 +133,7 @@ public class RevenueSharingAdsInfoBottomSheet extends BottomSheet {
buttonTextView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); buttonTextView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText));
buttonTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); buttonTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
buttonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); buttonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
buttonTextView.setText(LocaleController.getString("RevenueSharingAdsAlertButton", R.string.RevenueSharingAdsUnderstood)); buttonTextView.setText(LocaleController.getString("RevenueSharingAdsAlertButton", R.string.RevenueSharingAdsAlertButton));
buttonTextView.setBackground(Theme.AdaptiveRipple.filledRect(Theme.getColor(Theme.key_featuredStickers_addButton), 6)); buttonTextView.setBackground(Theme.AdaptiveRipple.filledRect(Theme.getColor(Theme.key_featuredStickers_addButton), 6));
buttonTextView.setOnClickListener(e -> dismiss()); buttonTextView.setOnClickListener(e -> dismiss());
linearLayout.addView(buttonTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, 0, 14, 22, 14, 14)); linearLayout.addView(buttonTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, 0, 14, 22, 14, 14));

View file

@ -72,6 +72,7 @@ import org.telegram.ui.Cells.StatisticPostInfoCell;
import org.telegram.ui.Charts.BarChartView; import org.telegram.ui.Charts.BarChartView;
import org.telegram.ui.Charts.BaseChartView; import org.telegram.ui.Charts.BaseChartView;
import org.telegram.ui.Charts.DoubleLinearChartView; import org.telegram.ui.Charts.DoubleLinearChartView;
import org.telegram.ui.Charts.LinearBarChartView;
import org.telegram.ui.Charts.LinearChartView; import org.telegram.ui.Charts.LinearChartView;
import org.telegram.ui.Charts.PieChartView; import org.telegram.ui.Charts.PieChartView;
import org.telegram.ui.Charts.StackBarChartView; import org.telegram.ui.Charts.StackBarChartView;
@ -924,7 +925,9 @@ public class StatisticActivity extends BaseFragment implements NotificationCente
public static final int VIEW_TYPE_LINEAR = 0; public static final int VIEW_TYPE_LINEAR = 0;
public static final int VIEW_TYPE_DOUBLE_LINEAR = 1; public static final int VIEW_TYPE_DOUBLE_LINEAR = 1;
public static final int VIEW_TYPE_STACKBAR = 2; public static final int VIEW_TYPE_STACKBAR = 2;
public static final int VIEW_TYPE_BAR = 3;
public static final int VIEW_TYPE_STACKLINEAR = 4; public static final int VIEW_TYPE_STACKLINEAR = 4;
public static final int VIEW_TYPE_BAR_LINEAR = 5;
class Adapter extends RecyclerListView.SelectionAdapter { class Adapter extends RecyclerListView.SelectionAdapter {
@ -1620,13 +1623,14 @@ public class StatisticActivity extends BaseFragment implements NotificationCente
checkboxContainer = new FrameLayout(context) { checkboxContainer = new FrameLayout(context) {
@Override @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec); final int width = MeasureSpec.getSize(widthMeasureSpec);
super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), heightMeasureSpec);
int currentW = 0; int currentW = 0;
int currentH = 0; int currentH = 0;
int n = getChildCount(); int n = getChildCount();
int firstH = n > 0 ? getChildAt(0).getMeasuredHeight() : 0; int firstH = n > 0 ? getChildAt(0).getMeasuredHeight() : 0;
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
if (currentW + getChildAt(i).getMeasuredWidth() > getMeasuredWidth()) { if (currentW + getChildAt(i).getMeasuredWidth() > width) {
currentW = 0; currentW = 0;
currentH += getChildAt(i).getMeasuredHeight(); currentH += getChildAt(i).getMeasuredHeight();
} }
@ -1678,6 +1682,12 @@ public class StatisticActivity extends BaseFragment implements NotificationCente
chartView.legendSignatureView.showPercentage = true; chartView.legendSignatureView.showPercentage = true;
zoomedChartView = new PieChartView(getContext()); zoomedChartView = new PieChartView(getContext());
break; break;
case 5:
chartView = new LinearBarChartView(getContext());
zoomedChartView = new LinearBarChartView(getContext());
zoomedChartView.legendSignatureView.useHour = true;
break;
case 0:
default: default:
chartView = new LinearChartView(getContext()); chartView = new LinearChartView(getContext());
zoomedChartView = new LinearChartView(getContext()); zoomedChartView = new LinearChartView(getContext());
@ -1719,7 +1729,7 @@ public class StatisticActivity extends BaseFragment implements NotificationCente
linearLayout.addView(chartHeaderView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 52)); linearLayout.addView(chartHeaderView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 52));
linearLayout.addView(frameLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); linearLayout.addView(frameLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
linearLayout.addView(checkboxContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.NO_GRAVITY, 16, 0, 16, 0)); linearLayout.addView(checkboxContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.FILL_HORIZONTAL, 16, 0, 16, 0));
if (chartType == 4) { if (chartType == 4) {
frameLayout.setClipChildren(false); frameLayout.setClipChildren(false);
@ -1913,8 +1923,8 @@ public class StatisticActivity extends BaseFragment implements NotificationCente
zoomedChartView.transitionParams = params; zoomedChartView.transitionParams = params;
chartView.transitionParams = params; chartView.transitionParams = params;
int max = 0; long max = 0;
int min = Integer.MAX_VALUE; long min = Integer.MAX_VALUE;
for (int i = 0; i < data.chartData.lines.size(); i++) { for (int i = 0; i < data.chartData.lines.size(); i++) {
if (data.chartData.lines.get(i).y[dateIndex] > max) if (data.chartData.lines.get(i).y[dateIndex] > max)
max = data.chartData.lines.get(i).y[dateIndex]; max = data.chartData.lines.get(i).y[dateIndex];

View file

@ -5672,6 +5672,10 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
storyViewer.unreadStateChanged = true; storyViewer.unreadStateChanged = true;
} }
} }
} else if (isActive && this.storyItem != null && storyViewer.storiesList != null) {
if (storyViewer.storiesList.markAsRead(this.storyItem.id)) {
storyViewer.unreadStateChanged = true;
}
} }
} }

View file

@ -2376,6 +2376,7 @@ public class StoriesController {
private final SortedSet<Integer> cachedObjects = new TreeSet<>(Comparator.reverseOrder()); private final SortedSet<Integer> cachedObjects = new TreeSet<>(Comparator.reverseOrder());
private final SortedSet<Integer> loadedObjects = new TreeSet<>(Comparator.reverseOrder()); private final SortedSet<Integer> loadedObjects = new TreeSet<>(Comparator.reverseOrder());
public final HashSet<Integer> seenStories = new HashSet<>();
private boolean showPhotos = true; private boolean showPhotos = true;
private boolean showVideos = true; private boolean showVideos = true;
@ -2471,6 +2472,7 @@ public class StoriesController {
final MessagesStorage storage = MessagesStorage.getInstance(currentAccount); final MessagesStorage storage = MessagesStorage.getInstance(currentAccount);
storage.getStorageQueue().postRunnable(() -> { storage.getStorageQueue().postRunnable(() -> {
SQLiteCursor cursor = null; SQLiteCursor cursor = null;
HashSet<Integer> seen = new HashSet<>();
HashSet<Long> loadUserIds = new HashSet<>(); HashSet<Long> loadUserIds = new HashSet<>();
HashSet<Long> loadChatIds = new HashSet<>(); HashSet<Long> loadChatIds = new HashSet<>();
ArrayList<MessageObject> cacheResult = new ArrayList<>(); ArrayList<MessageObject> cacheResult = new ArrayList<>();
@ -2478,7 +2480,7 @@ public class StoriesController {
final ArrayList<TLRPC.Chat> loadedChats = new ArrayList<>(); final ArrayList<TLRPC.Chat> loadedChats = new ArrayList<>();
try { try {
SQLiteDatabase database = storage.getDatabase(); SQLiteDatabase database = storage.getDatabase();
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data FROM profile_stories WHERE dialog_id = %d AND type = %d ORDER BY story_id DESC", dialogId, type)); cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, seen FROM profile_stories WHERE dialog_id = %d AND type = %d ORDER BY story_id DESC", dialogId, type));
while (cursor.next()) { while (cursor.next()) {
NativeByteBuffer data = cursor.byteBufferValue(0); NativeByteBuffer data = cursor.byteBufferValue(0);
if (data != null) { if (data != null) {
@ -2518,6 +2520,10 @@ public class StoriesController {
msg.generateThumbs(false); msg.generateThumbs(false);
cacheResult.add(msg); cacheResult.add(msg);
data.reuse(); data.reuse();
if (cursor.intValue(1) == 1) {
seen.add(storyItem.id);
}
} }
} }
cursor.dispose(); cursor.dispose();
@ -2549,6 +2555,7 @@ public class StoriesController {
return; return;
} }
seenStories.addAll(seen);
cachedObjects.clear(); cachedObjects.clear();
for (int i = 0; i < cacheResult.size(); ++i) { for (int i = 0; i < cacheResult.size(); ++i) {
pushObject(cacheResult.get(i), true); pushObject(cacheResult.get(i), true);
@ -2672,7 +2679,7 @@ public class StoriesController {
try { try {
SQLiteDatabase database = storage.getDatabase(); SQLiteDatabase database = storage.getDatabase();
database.executeFast(String.format(Locale.US, "DELETE FROM profile_stories WHERE dialog_id = %d AND type = %d", dialogId, type)).stepThis().dispose(); database.executeFast(String.format(Locale.US, "DELETE FROM profile_stories WHERE dialog_id = %d AND type = %d", dialogId, type)).stepThis().dispose();
state = database.executeFast("REPLACE INTO profile_stories VALUES(?, ?, ?, ?)"); state = database.executeFast("REPLACE INTO profile_stories VALUES(?, ?, ?, ?, ?)");
for (int i = 0; i < toSave.size(); ++i) { for (int i = 0; i < toSave.size(); ++i) {
MessageObject messageObject = toSave.get(i); MessageObject messageObject = toSave.get(i);
@ -2689,6 +2696,7 @@ public class StoriesController {
state.bindInteger(2, storyItem.id); state.bindInteger(2, storyItem.id);
state.bindByteBuffer(3, data); state.bindByteBuffer(3, data);
state.bindInteger(4, type); state.bindInteger(4, type);
state.bindInteger(5, seenStories.contains(storyItem.id) ? 1 : 0);
state.step(); state.step();
data.reuse(); data.reuse();
} }
@ -2707,6 +2715,18 @@ public class StoriesController {
}); });
} }
public boolean markAsRead(int storyId) {
if (seenStories.contains(storyId)) return false;
seenStories.add(storyId);
saveCache();
TL_stories.TL_stories_incrementStoryViews req = new TL_stories.TL_stories_incrementStoryViews();
req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId);
req.id.add(storyId);
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> {});
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.storiesReadUpdated);
return true;
}
private boolean canLoad() { private boolean canLoad() {
if (lastLoadTime == null) { if (lastLoadTime == null) {
return true; return true;

View file

@ -1602,6 +1602,14 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter.
private Utilities.Callback<Integer> onWidgetSelected; private Utilities.Callback<Integer> onWidgetSelected;
public EmojiBottomSheet whenWidgetSelected(Utilities.Callback<Integer> listener) { public EmojiBottomSheet whenWidgetSelected(Utilities.Callback<Integer> listener) {
this.onWidgetSelected = listener; this.onWidgetSelected = listener;
View[] pages = viewPager.getViewPages();
for (int i = 0; i < pages.length; ++i) {
View view = pages[i];
if (view instanceof Page) {
Page page = (Page) view;
page.adapter.update();
}
}
return this; return this;
} }

View file

@ -7,6 +7,7 @@ import android.graphics.Canvas;
import android.graphics.LinearGradient; import android.graphics.LinearGradient;
import android.graphics.Matrix; import android.graphics.Matrix;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Shader; import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
@ -212,6 +213,9 @@ public class StoryEntry {
if (drawable == null) { if (drawable == null) {
return; return;
} }
Rect rect = new Rect(drawable.getBounds());
Drawable.Callback callback = drawable.getCallback();
drawable.setCallback(null);
if (drawable instanceof BitmapDrawable) { if (drawable instanceof BitmapDrawable) {
BitmapDrawable bd = (BitmapDrawable) drawable; BitmapDrawable bd = (BitmapDrawable) drawable;
int bw = bd.getBitmap().getWidth(); int bw = bd.getBitmap().getWidth();
@ -223,6 +227,8 @@ public class StoryEntry {
drawable.setBounds(0, 0, w, h); drawable.setBounds(0, 0, w, h);
drawable.draw(canvas); drawable.draw(canvas);
} }
drawable.setBounds(rect);
drawable.setCallback(callback);
} }
public Bitmap buildBitmap(float scale, Bitmap mainFileBitmap) { public Bitmap buildBitmap(float scale, Bitmap mainFileBitmap) {

View file

@ -15,8 +15,11 @@ import androidx.annotation.RequiresApi;
import androidx.biometric.BiometricManager; import androidx.biometric.BiometricManager;
import androidx.biometric.BiometricPrompt; import androidx.biometric.BiometricPrompt;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleRegistry;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 925 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 746 B

After

Width:  |  Height:  |  Size: 714 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="72dp"
android:height="72dp"
android:viewportWidth="72"
android:viewportHeight="72">
<group
android:translateX="9.000000"
android:translateY="14.000000">
<path
android:strokeColor="#FFFFFF"
android:strokeWidth="7.2"
android:pathData="M2.96014341,0 L50.9898193,0 C51.9732032,-7.06402744e-15 52.7703933,0.797190129 52.7703933,1.78057399 C52.7703933,2.08038611 52.6946886,2.3753442 52.5502994,2.63809702 L29.699977,44.2200383 C28.7527832,45.9436969 26.5876295,46.5731461 24.8639708,45.6259523 C24.2556953,45.2916896 23.7583564,44.7869606 23.4331014,44.1738213 L1.38718565,2.61498853 C0.926351231,1.74626794 1.25700829,0.668450654 2.12572888,0.20761623 C2.38272962,0.0712838007 2.6692209,0 2.96014341,0 Z" />
<path
android:fillType="evenOdd"
android:strokeColor="#FFFFFF"
android:strokeWidth="7.2"
android:pathData="M 27 44.4532875 L 27 0" />
</group>
</vector>

View file

@ -11,7 +11,7 @@
<!--THEMES--> <!--THEMES-->
<style name="Theme.TMessages.Start" parent="@android:style/Theme.Material"> <style name="Theme.TMessages.Start" parent="Theme.AppCompat.DayNight">
<item name="android:windowActionBar">false</item> <item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item> <item name="android:windowNoTitle">true</item>
<item name="android:actionBarStyle">@style/ActionBar.Transparent.TMessages.Start</item> <item name="android:actionBarStyle">@style/ActionBar.Transparent.TMessages.Start</item>

View file

@ -11,7 +11,7 @@
<!--THEMES--> <!--THEMES-->
<style name="Theme.TMessages.Start" parent="@android:style/Theme.Material"> <style name="Theme.TMessages.Start" parent="Theme.AppCompat.Light">
<item name="android:windowActionBar">false</item> <item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item> <item name="android:windowNoTitle">true</item>
<item name="android:actionBarStyle">@style/ActionBar.Transparent.TMessages.Start</item> <item name="android:actionBarStyle">@style/ActionBar.Transparent.TMessages.Start</item>
@ -25,7 +25,7 @@
<item name="android:forceDarkAllowed">false</item> <item name="android:forceDarkAllowed">false</item>
</style> </style>
<style name="Theme.TMessages" parent="@android:style/Theme.Material.Light"> <style name="Theme.TMessages" parent="Theme.AppCompat.Light">
<item name="android:windowActionBar">false</item> <item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item> <item name="android:windowNoTitle">true</item>
<item name="android:windowActionBarOverlay">false</item> <item name="android:windowActionBarOverlay">false</item>
@ -52,7 +52,7 @@
<item name="android:forceDarkAllowed">false</item> <item name="android:forceDarkAllowed">false</item>
</style> </style>
<style name="Theme.TMessages.Dark" parent="@android:style/Theme.Material"> <style name="Theme.TMessages.Dark" parent="Theme.AppCompat.DayNight">
<item name="android:windowActionBar">false</item> <item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item> <item name="android:windowNoTitle">true</item>
<item name="android:windowActionBarOverlay">false</item> <item name="android:windowActionBarOverlay">false</item>

View file

@ -16,7 +16,7 @@
<resources> <resources>
<style name="Theme.TMessages.Start" parent="@android:style/Theme.Material"> <style name="Theme.TMessages.Start" parent="Theme.AppCompat.Light">
<item name="android:windowActionBar">false</item> <item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item> <item name="android:windowNoTitle">true</item>
<item name="android:actionBarStyle">@style/ActionBar.Transparent.TMessages.Start</item> <item name="android:actionBarStyle">@style/ActionBar.Transparent.TMessages.Start</item>
@ -33,7 +33,7 @@
<item name="android:windowSplashScreenBackground">?android:windowBackground</item> <item name="android:windowSplashScreenBackground">?android:windowBackground</item>
</style> </style>
<style name="Theme.TMessages" parent="@android:style/Theme.Material.Light"> <style name="Theme.TMessages" parent="Theme.AppCompat.Light">
<item name="android:windowActionBar">false</item> <item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item> <item name="android:windowNoTitle">true</item>
<item name="android:windowActionBarOverlay">false</item> <item name="android:windowActionBarOverlay">false</item>
@ -60,7 +60,7 @@
<item name="android:forceDarkAllowed">false</item> <item name="android:forceDarkAllowed">false</item>
</style> </style>
<style name="Theme.TMessages.Dark" parent="@android:style/Theme.Material"> <style name="Theme.TMessages.Dark" parent="Theme.AppCompat.DayNight">
<item name="android:windowActionBar">false</item> <item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item> <item name="android:windowNoTitle">true</item>
<item name="android:windowActionBarOverlay">false</item> <item name="android:windowActionBarOverlay">false</item>

View file

@ -1121,6 +1121,7 @@
<string name="SponsoredMessageAd">Ad</string> <string name="SponsoredMessageAd">Ad</string>
<string name="SponsoredMessageAdWhatIsThis">what\'s this?</string> <string name="SponsoredMessageAdWhatIsThis">what\'s this?</string>
<string name="SponsoredMessageSponsor">Advertiser Info</string> <string name="SponsoredMessageSponsor">Advertiser Info</string>
<string name="SponsoredMessageSponsorReportable">Sponsor Info</string>
<string name="SponsoredMessageInfo">What are sponsored\nmessages?</string> <string name="SponsoredMessageInfo">What are sponsored\nmessages?</string>
<string name="SponsoredMessageInfo2Description1">Unlike other apps, Telegram never uses your private data to target ads. [Learn more in the Privacy Policy](https://telegram.org/privacy#5-6-no-ads-based-on-user-data)</string> <string name="SponsoredMessageInfo2Description1">Unlike other apps, Telegram never uses your private data to target ads. [Learn more in the Privacy Policy](https://telegram.org/privacy#5-6-no-ads-based-on-user-data)</string>
<string name="SponsoredMessageInfo2Description2">Unlike other apps, Telegram doesn\'t track whether you tapped on a sponsored message and doesn\'t profile you based on your activity. We also prevent external links in sponsored messages to ensure that third parties cant spy on our users. We believe that everyone has the right to privacy, and technological platforms should respect that.</string> <string name="SponsoredMessageInfo2Description2">Unlike other apps, Telegram doesn\'t track whether you tapped on a sponsored message and doesn\'t profile you based on your activity. We also prevent external links in sponsored messages to ensure that third parties cant spy on our users. We believe that everyone has the right to privacy, and technological platforms should respect that.</string>
@ -1138,9 +1139,9 @@
<string name="RevenueSharingAdsInfo3Title">Can Be Removed</string> <string name="RevenueSharingAdsInfo3Title">Can Be Removed</string>
<string name="RevenueSharingAdsInfo3Subtitle">You can turn off ads by subscribing to **Telegram Premium**, and Level %1$s channels can remove them for their subscribers.</string> <string name="RevenueSharingAdsInfo3Subtitle">You can turn off ads by subscribing to **Telegram Premium**, and Level %1$s channels can remove them for their subscribers.</string>
<string name="RevenueSharingAdsInfo4Title">Can I Launch an Ad?</string> <string name="RevenueSharingAdsInfo4Title">Can I Launch an Ad?</string>
<string name="RevenueSharingAdsInfo4Subtitle">Anyone can create an ad to display in this channel — with minimal budgets. Check out the **Telegram Ad Platform** for details. %1$s</string> <string name="RevenueSharingAdsInfo4Subtitle2">Anyone can create an ad to display in this channel — with minimal budgets. Check out the **Telegram Ad Platform** for details. %1$s</string>
<string name="RevenueSharingAdsInfo4SubtitleLearnMore">**Learn More >**</string> <string name="RevenueSharingAdsInfo4SubtitleLearnMore">**Learn More >**</string>
<string name="RevenueSharingAdsUnderstood">Understood</string> <string name="RevenueSharingAdsAlertButton">Understood</string>
<string name="PromoteUrl">https://ads.telegram.org</string> <string name="PromoteUrl">https://ads.telegram.org</string>
<string name="InstantViewNightMode">The dark theme will turn automatically during night time</string> <string name="InstantViewNightMode">The dark theme will turn automatically during night time</string>
<string name="InstantViewReference">Reference</string> <string name="InstantViewReference">Reference</string>
@ -8585,6 +8586,8 @@
<string name="MonetizationGraphImpressions">Ad impressions</string> <string name="MonetizationGraphImpressions">Ad impressions</string>
<string name="MonetizationGraphRevenue">Ad revenue</string> <string name="MonetizationGraphRevenue">Ad revenue</string>
<string name="MonetizationWithdraw">Withdraw via Fragment</string> <string name="MonetizationWithdraw">Withdraw via Fragment</string>
<string name="MonetizationChartInTON">%s in TON</string>
<string name="MonetizationChartInUSD">%s in USD</string>
<string name="BotAllowBiometryTitle">Allow biometry</string> <string name="BotAllowBiometryTitle">Allow biometry</string>
<string name="BotAllowBiometryMessage">Do you want to allow **%s** to use biometry?</string> <string name="BotAllowBiometryMessage">Do you want to allow **%s** to use biometry?</string>
<string name="DownloadSpeedLimited">Download speed limited</string> <string name="DownloadSpeedLimited">Download speed limited</string>

View file

@ -3,7 +3,7 @@
<!--THEMES--> <!--THEMES-->
<style name="Theme.TMessages.Start" parent="@android:style/Theme.Holo.Light"> <style name="Theme.TMessages.Start" parent="Theme.AppCompat.Light">
<item name="android:windowActionBar">false</item> <item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item> <item name="android:windowNoTitle">true</item>
<item name="android:actionBarStyle">@style/ActionBar.Transparent.TMessages.Start</item> <item name="android:actionBarStyle">@style/ActionBar.Transparent.TMessages.Start</item>
@ -13,7 +13,7 @@
<item name="android:textViewStyle">@style/MyTextViewStyle</item> <item name="android:textViewStyle">@style/MyTextViewStyle</item>
</style> </style>
<style name="Theme.TMessages" parent="@android:style/Theme.Holo.Light"> <style name="Theme.TMessages" parent="Theme.AppCompat.Light">
<item name="android:windowActionBar">false</item> <item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item> <item name="android:windowNoTitle">true</item>
<item name="android:windowActionBarOverlay">false</item> <item name="android:windowActionBarOverlay">false</item>
@ -27,7 +27,7 @@
<item name="android:textViewStyle">@style/MyTextViewStyle</item> <item name="android:textViewStyle">@style/MyTextViewStyle</item>
</style> </style>
<style name="Theme.TMessages.Dark" parent="@android:style/Theme.Holo"> <style name="Theme.TMessages.Dark" parent="Theme.AppCompat.DayNight">
<item name="android:windowActionBar">false</item> <item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item> <item name="android:windowNoTitle">true</item>
<item name="android:windowActionBarOverlay">false</item> <item name="android:windowActionBarOverlay">false</item>

View file

@ -13,8 +13,8 @@
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true # org.gradle.parallel=true
#Sat Mar 12 05:53:50 MSK 2016 #Sat Mar 12 05:53:50 MSK 2016
APP_VERSION_CODE=4571 APP_VERSION_CODE=4583
APP_VERSION_NAME=10.10.0 APP_VERSION_NAME=10.10.1
APP_PACKAGE=org.telegram.messenger APP_PACKAGE=org.telegram.messenger
RELEASE_KEY_PASSWORD=android RELEASE_KEY_PASSWORD=android
RELEASE_KEY_ALIAS=androidkey RELEASE_KEY_ALIAS=androidkey