diff --git a/Telegram/Resources/uwp/AppX/AppxManifest.xml b/Telegram/Resources/uwp/AppX/AppxManifest.xml
index 040bb1cfa1..9a1695274e 100644
--- a/Telegram/Resources/uwp/AppX/AppxManifest.xml
+++ b/Telegram/Resources/uwp/AppX/AppxManifest.xml
@@ -9,7 +9,7 @@
+ Version="1.0.10.0" />
Telegram Desktop
Telegram Messenger LLP
diff --git a/Telegram/Resources/winrc/Telegram.rc b/Telegram/Resources/winrc/Telegram.rc
index a40279cd05..c714c554ae 100644
--- a/Telegram/Resources/winrc/Telegram.rc
+++ b/Telegram/Resources/winrc/Telegram.rc
@@ -34,8 +34,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,0,9,0
- PRODUCTVERSION 1,0,9,0
+ FILEVERSION 1,0,10,0
+ PRODUCTVERSION 1,0,10,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -52,10 +52,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Telegram Messenger LLP"
VALUE "FileDescription", "Telegram Desktop official messenger"
- VALUE "FileVersion", "1.0.9.0"
+ VALUE "FileVersion", "1.0.10.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2017"
VALUE "ProductName", "Telegram Desktop"
- VALUE "ProductVersion", "1.0.9.0"
+ VALUE "ProductVersion", "1.0.10.0"
END
END
BLOCK "VarFileInfo"
diff --git a/Telegram/Resources/winrc/Updater.rc b/Telegram/Resources/winrc/Updater.rc
index 590ad6c18e..bd944d0257 100644
--- a/Telegram/Resources/winrc/Updater.rc
+++ b/Telegram/Resources/winrc/Updater.rc
@@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,0,9,0
- PRODUCTVERSION 1,0,9,0
+ FILEVERSION 1,0,10,0
+ PRODUCTVERSION 1,0,10,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -43,10 +43,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Telegram Messenger LLP"
VALUE "FileDescription", "Telegram Desktop Updater"
- VALUE "FileVersion", "1.0.9.0"
+ VALUE "FileVersion", "1.0.10.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2017"
VALUE "ProductName", "Telegram Desktop"
- VALUE "ProductVersion", "1.0.9.0"
+ VALUE "ProductVersion", "1.0.10.0"
END
END
BLOCK "VarFileInfo"
diff --git a/Telegram/SourceFiles/application.cpp b/Telegram/SourceFiles/application.cpp
index 6bc4b8ded5..e277ecd41a 100644
--- a/Telegram/SourceFiles/application.cpp
+++ b/Telegram/SourceFiles/application.cpp
@@ -1069,8 +1069,8 @@ void AppClass::checkMapVersion() {
if (Local::oldMapVersion() < AppVersion) {
if (Local::oldMapVersion()) {
QString versionFeatures;
- if ((cAlphaVersion() || cBetaVersion()) && Local::oldMapVersion() < 1000008) {
- versionFeatures = QString::fromUtf8("\xe2\x80\x94 Click and drag on waveform to play audio from a chosen moment.");
+ if ((cAlphaVersion() || cBetaVersion()) && Local::oldMapVersion() < 1000010) {
+ versionFeatures = QString::fromUtf8("\xe2\x80\x94 More different emoticons supported.\n\xe2\x80\x94 Bug fixes and other minor improvements.");
} else if (!(cAlphaVersion() || cBetaVersion()) && Local::oldMapVersion() < 1000005) {
versionFeatures = langNewVersionText();
} else {
diff --git a/Telegram/SourceFiles/core/version.h b/Telegram/SourceFiles/core/version.h
index 0fe4fcd57c..3e6d529ed3 100644
--- a/Telegram/SourceFiles/core/version.h
+++ b/Telegram/SourceFiles/core/version.h
@@ -24,7 +24,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#define BETA_VERSION_MACRO (0ULL)
-constexpr int AppVersion = 1000009;
-constexpr str_const AppVersionStr = "1.0.9";
+constexpr int AppVersion = 1000010;
+constexpr str_const AppVersionStr = "1.0.10";
constexpr bool AppAlphaVersion = true;
constexpr uint64 AppBetaVersion = BETA_VERSION_MACRO;
diff --git a/Telegram/SourceFiles/dialogs/dialogs_layout.cpp b/Telegram/SourceFiles/dialogs/dialogs_layout.cpp
index b4710d6a95..fff4097b30 100644
--- a/Telegram/SourceFiles/dialogs/dialogs_layout.cpp
+++ b/Telegram/SourceFiles/dialogs/dialogs_layout.cpp
@@ -109,15 +109,27 @@ void paintRow(Painter &p, const RippleRow *row, History *history, HistoryItem *i
p.restoreTextPalette();
}
} else if (!item) {
+ auto availableWidth = namewidth;
+ if (history->isPinnedDialog()) {
+ auto &icon = (active ? st::dialogsPinnedIconActive : (selected ? st::dialogsPinnedIconOver : st::dialogsPinnedIcon));
+ icon.paint(p, fullWidth - st::dialogsPadding.x() - icon.width(), texttop, fullWidth);
+ availableWidth -= icon.width() + st::dialogsUnreadPadding;
+ }
+
auto &color = active ? st::dialogsTextFgServiceActive : (selected ? st::dialogsTextFgServiceOver : st::dialogsTextFgService);
p.setFont(st::dialogsTextFont);
- if (!history->paintSendAction(p, nameleft, texttop, namewidth, fullWidth, color, ms)) {
+ if (!history->paintSendAction(p, nameleft, texttop, availableWidth, fullWidth, color, ms)) {
// Empty history
}
} else if (!item->isEmpty()) {
paintRowDate(p, date, rectForName, active, selected);
paintItemCallback(nameleft, namewidth, item);
+ } else if (history->isPinnedDialog()) {
+ auto availableWidth = namewidth;
+ auto &icon = (active ? st::dialogsPinnedIconActive : (selected ? st::dialogsPinnedIconOver : st::dialogsPinnedIcon));
+ icon.paint(p, fullWidth - st::dialogsPadding.x() - icon.width(), texttop, fullWidth);
+ availableWidth -= icon.width() + st::dialogsUnreadPadding;
}
auto sendStateIcon = ([draft, item, active, selected]() -> const style::icon* {
if (draft) {
diff --git a/Telegram/SourceFiles/dialogswidget.cpp b/Telegram/SourceFiles/dialogswidget.cpp
index 6e7f1451c6..24a1e93811 100644
--- a/Telegram/SourceFiles/dialogswidget.cpp
+++ b/Telegram/SourceFiles/dialogswidget.cpp
@@ -643,17 +643,12 @@ void DialogsInner::savePinnedOrder() {
if (newOrder.size() != _pinnedOrder.size()) {
return; // Something has changed in the set of pinned chats.
}
-
- auto peers = QVector();
- peers.reserve(newOrder.size());
for_const (auto history, newOrder) {
if (_pinnedOrder.indexOf(history) < 0) {
return; // Something has changed in the set of pinned chats.
}
- peers.push_back(history->peer->input);
}
- auto flags = MTPmessages_ReorderPinnedDialogs::Flag::f_force;
- MTP::send(MTPmessages_ReorderPinnedDialogs(MTP_flags(qFlags(flags)), MTP_vector(peers)));
+ App::histories().savePinnedToServer();
}
void DialogsInner::finishReorderPinned() {
diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp
index 63cc3a55c7..0c20417ba4 100644
--- a/Telegram/SourceFiles/history.cpp
+++ b/Telegram/SourceFiles/history.cpp
@@ -719,6 +719,17 @@ QList Histories::getPinnedOrder() const {
return result;
}
+void Histories::savePinnedToServer() const {
+ auto order = getPinnedOrder();
+ auto peers = QVector();
+ peers.reserve(order.size());
+ for_const (auto history, order) {
+ peers.push_back(history->peer->input);
+ }
+ auto flags = MTPmessages_ReorderPinnedDialogs::Flag::f_force;
+ MTP::send(MTPmessages_ReorderPinnedDialogs(MTP_flags(qFlags(flags)), MTP_vector(peers)));
+}
+
HistoryItem *History::createItem(const MTPMessage &msg, bool applyServiceAction, bool detachExistingItem) {
auto msgId = MsgId(0);
switch (msg.type()) {
diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h
index 50c500c27c..1f424a1ef7 100644
--- a/Telegram/SourceFiles/history.h
+++ b/Telegram/SourceFiles/history.h
@@ -83,6 +83,7 @@ public:
void clearPinned();
int pinnedCount() const;
QList getPinnedOrder() const;
+ void savePinnedToServer() const;
struct SendActionAnimationUpdate {
History *history;
diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp
index b93bc1495b..f5192e0b9c 100644
--- a/Telegram/SourceFiles/mainwidget.cpp
+++ b/Telegram/SourceFiles/mainwidget.cpp
@@ -1976,7 +1976,25 @@ void MainWidget::fillPeerMenu(PeerData *peer, base::lambdaisPinnedDialog();
if (isPinned && App::histories().pinnedCount() >= Global::PinnedDialogsCountMax()) {
- Ui::show(Box(lng_error_pinned_max(lt_count, Global::PinnedDialogsCountMax())));
+ // Some old chat, that was converted to supergroup, maybe is still pinned.
+ auto findWastedPin = []() -> History* {
+ auto order = App::histories().getPinnedOrder();
+ for_const (auto pinned, order) {
+ if (pinned->peer->isChat()
+ && pinned->peer->asChat()->isDeactivated()
+ && !pinned->inChatList(Dialogs::Mode::All)) {
+ return pinned;
+ }
+ }
+ return nullptr;
+ };
+ if (auto wasted = findWastedPin()) {
+ wasted->setPinnedDialog(false);
+ history->setPinnedDialog(isPinned);
+ App::histories().savePinnedToServer();
+ } else {
+ Ui::show(Box(lng_error_pinned_max(lt_count, Global::PinnedDialogsCountMax())));
+ }
return;
}
diff --git a/Telegram/SourceFiles/structs.cpp b/Telegram/SourceFiles/structs.cpp
index ed70ce7ca9..0bb0c04e63 100644
--- a/Telegram/SourceFiles/structs.cpp
+++ b/Telegram/SourceFiles/structs.cpp
@@ -1659,20 +1659,54 @@ void DocumentData::notifyLayoutChanged() const {
}
VoiceWaveform documentWaveformDecode(const QByteArray &encoded5bit) {
- VoiceWaveform result((encoded5bit.size() * 8) / 5, 0);
- for (int32 i = 0, l = result.size(); i < l; ++i) { // read each 5 bit of encoded5bit as 0-31 unsigned char
- int32 byte = (i * 5) / 8, shift = (i * 5) % 8;
- result[i] = (((*(uint16*)(encoded5bit.constData() + byte)) >> shift) & 0x1F);
+ auto bitsCount = static_cast(encoded5bit.size() * 8);
+ auto valuesCount = bitsCount / 5;
+ if (!valuesCount) {
+ return VoiceWaveform();
}
+
+ // Read each 5 bit of encoded5bit as 0-31 unsigned char.
+ // We count the index of the byte in which the desired 5-bit sequence starts.
+ // And then we read a uint16 starting from that byte to guarantee to get all of those 5 bits.
+ //
+ // BUT! if it is the last byte we have, we're not allowed to read a uint16 starting with it.
+ // Because it will be an overflow (we'll access one byte after the available memory).
+ // We see, that only the last 5 bits could start in the last available byte and be problematic.
+ // So we read in a general way all the entries in a general way except the last one.
+ auto result = VoiceWaveform(valuesCount, 0);
+ auto bitsData = encoded5bit.constData();
+ for (auto i = 0, l = valuesCount - 1; i != l; ++i) {
+ auto byteIndex = (i * 5) / 8;
+ auto bitShift = (i * 5) % 8;
+ auto value = *reinterpret_cast(bitsData + byteIndex);
+ result[i] = static_cast((value >> bitShift) & 0x1F);
+ }
+ auto lastByteIndex = ((valuesCount - 1) * 5) / 8;
+ auto lastBitShift = ((valuesCount - 1) * 5) % 8;
+ auto lastValue = (lastByteIndex == encoded5bit.size() - 1)
+ ? static_cast(*reinterpret_cast(bitsData + lastByteIndex))
+ : *reinterpret_cast(bitsData + lastByteIndex);
+ result[valuesCount - 1] = static_cast((lastValue >> lastBitShift) & 0x1F);
+
return result;
}
QByteArray documentWaveformEncode5bit(const VoiceWaveform &waveform) {
- QByteArray result((waveform.size() * 5 + 7) / 8, 0);
- for (int32 i = 0, l = waveform.size(); i < l; ++i) { // write each 0-31 unsigned char as 5 bit to result
- int32 byte = (i * 5) / 8, shift = (i * 5) % 8;
- (*(uint16*)(result.data() + byte)) |= (uint16(waveform.at(i) & 0x1F) << shift);
+ auto bitsCount = waveform.size() * 5;
+ auto bytesCount = (bitsCount + 7) / 8;
+ auto result = QByteArray(bytesCount + 1, 0);
+ auto bitsData = result.data();
+
+ // Write each 0-31 unsigned char as 5 bit to result.
+ // We reserve one extra byte to be able to dereference any of required bytes
+ // as a uint16 without overflowing, even the byte with index "bytesCount - 1".
+ for (auto i = 0, l = waveform.size(); i < l; ++i) {
+ auto byteIndex = (i * 5) / 8;
+ auto bitShift = (i * 5) % 8;
+ auto value = (static_cast(waveform[i]) & 0x1F) << bitShift;
+ *reinterpret_cast(bitsData + byteIndex) |= value;
}
+ result.resize(bytesCount);
return result;
}
diff --git a/Telegram/build/version b/Telegram/build/version
index 405397a642..3707807fa6 100644
--- a/Telegram/build/version
+++ b/Telegram/build/version
@@ -1,6 +1,6 @@
-AppVersion 1000009
+AppVersion 1000010
AppVersionStrMajor 1.0
-AppVersionStrSmall 1.0.9
-AppVersionStr 1.0.9
+AppVersionStrSmall 1.0.10
+AppVersionStr 1.0.10
AlphaChannel 1
BetaVersion 0