diff --git a/Telegram/Resources/uwp/AppX/AppxManifest.xml b/Telegram/Resources/uwp/AppX/AppxManifest.xml
index 9feaa42a4..bd983f529 100644
--- a/Telegram/Resources/uwp/AppX/AppxManifest.xml
+++ b/Telegram/Resources/uwp/AppX/AppxManifest.xml
@@ -9,7 +9,7 @@
+ Version="2.0.1.0" />
Telegram Desktop
Telegram FZ-LLC
diff --git a/Telegram/SourceFiles/api/api_sending.cpp b/Telegram/SourceFiles/api/api_sending.cpp
index d0c5315ac..eaac3957e 100644
--- a/Telegram/SourceFiles/api/api_sending.cpp
+++ b/Telegram/SourceFiles/api/api_sending.cpp
@@ -200,7 +200,7 @@ void SendExistingPhoto(
bool SendDice(Api::MessageToSend &message) {
static const auto kDiceString = QString::fromUtf8("\xF0\x9F\x8E\xB2");
- if (message.textWithTags.text != kDiceString) {
+ if (message.textWithTags.text.midRef(0).trimmed() != kDiceString) {
return false;
}
const auto history = message.action.history;
diff --git a/Telegram/SourceFiles/core/changelogs.cpp b/Telegram/SourceFiles/core/changelogs.cpp
index 76c890ca4..e449f4afa 100644
--- a/Telegram/SourceFiles/core/changelogs.cpp
+++ b/Telegram/SourceFiles/core/changelogs.cpp
@@ -54,6 +54,15 @@ std::map BetaLogs() {
1009022,
"\xE2\x80\xA2 Organize chats into Chat Folders "
"if you have too many chats.\n"
+ },
+ {
+ 2000001,
+ "\xE2\x80\xA2 Switch between folders using Ctrl+1, ..., Ctrl+8.\n"
+
+ "\xE2\x80\xA2 Fix crash when a pinned in folder chat "
+ "was added to archive.\n"
+
+ "\xE2\x80\xA2 Fix font issues in Linux version."
}
};
};
diff --git a/Telegram/SourceFiles/core/shortcuts.cpp b/Telegram/SourceFiles/core/shortcuts.cpp
index 7cfcf02d4..1fd246bc0 100644
--- a/Telegram/SourceFiles/core/shortcuts.cpp
+++ b/Telegram/SourceFiles/core/shortcuts.cpp
@@ -117,7 +117,7 @@ public:
void fill();
void clear();
- std::optional lookup(int shortcutId) const;
+ [[nodiscard]] std::vector lookup(int shortcutId) const;
void toggleMedia(bool toggled);
void toggleSupport(bool toggled);
@@ -128,14 +128,14 @@ private:
void writeDefaultFile();
bool readCustomFile();
- void set(const QString &keys, Command command);
+ void set(const QString &keys, Command command, bool replace = false);
void remove(const QString &keys);
void unregister(base::unique_qptr shortcut);
QStringList _errors;
base::flat_map> _shortcuts;
- base::flat_map _commandByShortcutId;
+ base::flat_multi_map _commandByShortcutId;
base::flat_set _mediaShortcuts;
base::flat_set _supportShortcuts;
@@ -210,11 +210,14 @@ const QStringList &Manager::errors() const {
return _errors;
}
-std::optional Manager::lookup(int shortcutId) const {
- const auto i = _commandByShortcutId.find(shortcutId);
- return (i != end(_commandByShortcutId))
- ? base::make_optional(i->second)
- : std::nullopt;
+std::vector Manager::lookup(int shortcutId) const {
+ auto result = std::vector();
+ auto i = _commandByShortcutId.findFirst(shortcutId);
+ const auto end = _commandByShortcutId.end();
+ for (; i != end && (i->first == shortcutId); ++i) {
+ result.push_back(i->second);
+ }
+ return result;
}
void Manager::toggleMedia(bool toggled) {
@@ -282,7 +285,7 @@ bool Manager::readCustomFile() {
const auto name = (*command).toString();
const auto i = CommandByName.find(name);
if (i != end(CommandByName)) {
- set((*keys).toString(), i->second);
+ set((*keys).toString(), i->second, true);
} else {
LOG(("Shortcut Warning: "
"could not find shortcut command handler '%1'"
@@ -347,7 +350,7 @@ void Manager::fillDefaults() {
ranges::view::ints(1, ranges::unreachable));
for (const auto [command, index] : folders) {
- set(qsl("%1+shift+%2").arg(ctrl).arg(index > 9 ? 0 : index), command);
+ set(qsl("%1+%2").arg(ctrl).arg(index), command);
}
set(qsl("%1+shift+down").arg(ctrl), Command::FolderNext);
@@ -379,10 +382,12 @@ void Manager::writeDefaultFile() {
shortcuts.push_back(version);
for (const auto &[sequence, shortcut] : _shortcuts) {
- const auto i = _commandByShortcutId.find(shortcut->id());
- if (i != end(_commandByShortcutId)) {
+ const auto shortcutId = shortcut->id();
+ auto i = _commandByShortcutId.findFirst(shortcutId);
+ const auto end = _commandByShortcutId.end();
+ for (; i != end && i->first == shortcutId; ++i) {
const auto j = CommandNames.find(i->second);
- if (j != end(CommandNames)) {
+ if (j != CommandNames.end()) {
QJsonObject entry;
entry.insert(qsl("keys"), sequence.toString().toLower());
entry.insert(qsl("command"), j->second);
@@ -396,7 +401,7 @@ void Manager::writeDefaultFile() {
file.write(document.toJson(QJsonDocument::Indented));
}
-void Manager::set(const QString &keys, Command command) {
+void Manager::set(const QString &keys, Command command, bool replace) {
if (keys.isEmpty()) {
return;
}
@@ -421,22 +426,25 @@ void Manager::set(const QString &keys, Command command) {
if (isMediaShortcut || isSupportShortcut) {
shortcut->setEnabled(false);
}
- const auto id = shortcut->id();
+ auto id = shortcut->id();
+ auto i = _shortcuts.find(result);
+ if (i == end(_shortcuts)) {
+ i = _shortcuts.emplace(result, std::move(shortcut)).first;
+ } else if (replace) {
+ unregister(std::exchange(i->second, std::move(shortcut)));
+ } else {
+ shortcut = nullptr;
+ id = i->second->id();
+ }
if (!id) {
_errors.push_back(qsl("Could not create shortcut '%1'!").arg(keys));
return;
}
- auto i = _shortcuts.find(result);
- if (i == end(_shortcuts)) {
- i = _shortcuts.emplace(result, std::move(shortcut)).first;
- } else {
- unregister(std::exchange(i->second, std::move(shortcut)));
- }
_commandByShortcutId.emplace(id, command);
- if (isMediaShortcut) {
+ if (shortcut && isMediaShortcut) {
_mediaShortcuts.emplace(i->second.get());
}
- if (isSupportShortcut) {
+ if (shortcut && isSupportShortcut) {
_supportShortcuts.emplace(i->second.get());
}
}
@@ -471,11 +479,13 @@ Manager Data;
} // namespace
-Request::Request(Command command) : _command(command) {
+Request::Request(std::vector commands)
+: _commands(std::move(commands)) {
}
bool Request::check(Command command, int priority) {
- if (_command == command && priority > _handlerPriority) {
+ if (ranges::contains(_commands, command)
+ && priority > _handlerPriority) {
_handlerPriority = priority;
return true;
}
@@ -487,12 +497,16 @@ bool Request::handle(FnMut handler) {
return true;
}
-FnMut RequestHandler(Command command) {
- auto request = Request(command);
+FnMut RequestHandler(std::vector commands) {
+ auto request = Request(std::move(commands));
RequestsStream.fire(&request);
return std::move(request._handler);
}
+FnMut RequestHandler(Command command) {
+ return RequestHandler(std::vector{ command });
+}
+
bool Launch(Command command) {
if (auto handler = RequestHandler(command)) {
return handler();
@@ -500,6 +514,13 @@ bool Launch(Command command) {
return false;
}
+bool Launch(std::vector commands) {
+ if (auto handler = RequestHandler(std::move(commands))) {
+ return handler();
+ }
+ return false;
+}
+
rpl::producer> Requests() {
return RequestsStream.events();
}
@@ -515,10 +536,7 @@ const QStringList &Errors() {
}
bool HandleEvent(not_null event) {
- if (const auto command = Data.lookup(event->shortcutId())) {
- return Launch(*command);
- }
- return false;
+ return Launch(Data.lookup(event->shortcutId()));
}
void ToggleMediaShortcuts(bool toggled) {
diff --git a/Telegram/SourceFiles/core/shortcuts.h b/Telegram/SourceFiles/core/shortcuts.h
index 5929e22b5..fe2595dd3 100644
--- a/Telegram/SourceFiles/core/shortcuts.h
+++ b/Telegram/SourceFiles/core/shortcuts.h
@@ -35,16 +35,14 @@ enum class Command {
ChatPinned4,
ChatPinned5,
+ ShowAllChats,
ShowFolder1,
ShowFolder2,
ShowFolder3,
ShowFolder4,
ShowFolder5,
ShowFolder6,
- ShowFolder7,
- ShowFolder8,
- ShowFolder9,
- ShowFolder10,
+ ShowFolderLast,
FolderNext,
FolderPrevious,
@@ -65,16 +63,14 @@ enum class Command {
};
constexpr auto kShowFolder = {
+ Command::ShowAllChats,
Command::ShowFolder1,
Command::ShowFolder2,
Command::ShowFolder3,
Command::ShowFolder4,
Command::ShowFolder5,
Command::ShowFolder6,
- Command::ShowFolder7,
- Command::ShowFolder8,
- Command::ShowFolder9,
- Command::ShowFolder10,
+ Command::ShowFolderLast,
};
[[nodiscard]] FnMut RequestHandler(Command command);
@@ -85,13 +81,13 @@ public:
bool handle(FnMut handler);
private:
- explicit Request(Command command);
+ explicit Request(std::vector commands);
- Command _command;
+ std::vector _commands;
int _handlerPriority = -1;
FnMut _handler;
- friend FnMut RequestHandler(Command command);
+ friend FnMut RequestHandler(std::vector commands);
};
diff --git a/Telegram/SourceFiles/core/version.h b/Telegram/SourceFiles/core/version.h
index d7d9fabc5..ecbc0093e 100644
--- a/Telegram/SourceFiles/core/version.h
+++ b/Telegram/SourceFiles/core/version.h
@@ -22,8 +22,8 @@ constexpr auto AppId = "{C4A4AE8F-B9F7-4CC7-8A6C-BF7EEE87ACA5}"_cs;
constexpr auto AppNameOld = "Telegram Win (Unofficial)"_cs;
constexpr auto AppName = "Kotatogram Desktop"_cs;
constexpr auto AppFile = "Kotatogram"_cs;
-constexpr auto AppVersion = 2000000;
-constexpr auto AppVersionStr = "2.0";
+constexpr auto AppVersion = 2000001;
+constexpr auto AppVersionStr = "2.0.1";
constexpr auto AppBetaVersion = false;
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;
constexpr auto AppKotatoVersion = 1002001;
diff --git a/Telegram/SourceFiles/dialogs/dialogs.style b/Telegram/SourceFiles/dialogs/dialogs.style
index 96c759506..3583eea60 100644
--- a/Telegram/SourceFiles/dialogs/dialogs.style
+++ b/Telegram/SourceFiles/dialogs/dialogs.style
@@ -87,6 +87,14 @@ dialogsTextPaletteArchiveActive: TextPalette(defaultTextPalette) {
linkFg: dialogsTextFgActive;
}
+dialogsEmptyHeight: 160px;
+dialogsEmptySkip: 2px;
+dialogsEmptyLabel: FlatLabel(defaultFlatLabel) {
+ minWidth: 32px;
+ align: align(top);
+ textFg: windowSubTextFg;
+}
+
dialogsMenuToggle: IconButton {
width: 40px;
height: 40px;
diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp
index 349184b99..7f506ea79 100644
--- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp
+++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp
@@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/shortcuts.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/popup_menu.h"
+#include "ui/text/text_utilities.h"
#include "ui/text_options.h"
#include "ui/ui_utility.h"
#include "data/data_drafts.h"
@@ -123,8 +124,6 @@ InnerWidget::InnerWidget(
, _pinnedShiftAnimation([=](crl::time now) {
return pinnedShiftAnimationCallback(now);
})
-, _addContactLnk(this, tr::lng_add_contact_button(tr::now))
-, _editFilterLnk(this, tr::lng_filters_context_edit(tr::now))
, _cancelSearchInChat(this, st::dialogsCancelSearchInPeer)
, _cancelSearchFromUser(this, st::dialogsCancelSearchInPeer) {
@@ -132,8 +131,6 @@ InnerWidget::InnerWidget(
setAttribute(Qt::WA_OpaquePaintEvent, true);
#endif // OS_MAC_OLD
- _addContactLnk->addClickHandler([] { App::wnd()->onShowAddContact(); });
- _editFilterLnk->addClickHandler([=] { editOpenedFilter(); });
_cancelSearchInChat->setClickedCallback([=] { cancelSearchInChat(); });
_cancelSearchInChat->hide();
_cancelSearchFromUser->setClickedCallback([=] {
@@ -154,6 +151,7 @@ InnerWidget::InnerWidget(
session().data().contactsLoaded().changes(
) | rpl::start_with_next([=] {
refresh();
+ refreshEmptyLabel();
}, lifetime());
session().data().itemRemoved(
@@ -196,7 +194,9 @@ InnerWidget::InnerWidget(
setupOnlineStatusCheck();
- session().data().chatsListChanges(
+ rpl::merge(
+ session().data().chatsListChanges(),
+ session().data().chatsListLoadedEvents()
) | rpl::filter([=](Data::Folder *folder) {
return (folder == _openedFolder);
}) | rpl::start_with_next([=] {
@@ -511,19 +511,6 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
}
if (!otherStart) {
p.fillRect(dialogsClip, st::dialogsBg);
- p.setFont(st::noContactsFont);
- p.setPen(st::noContactsColor);
- const auto phrase = _filterId
- ? (session().data().chatsList()->loaded()
- ? tr::lng_no_chats_filter(tr::now)
- : tr::lng_contacts_loading(tr::now))
- : session().data().contactsLoaded().current()
- ? tr::lng_no_chats(tr::now)
- : tr::lng_contacts_loading(tr::now);
- p.drawText(
- QRect(0, 0, fullWidth, st::noContactsHeight - (session().data().contactsLoaded().current() ? st::noContactsFont->height : 0)),
- phrase,
- style::al_center);
}
} else if (_state == WidgetState::Filtered) {
if (!_hashtagResults.empty()) {
@@ -1441,8 +1428,7 @@ void InnerWidget::setSearchedPressed(int pressed) {
}
void InnerWidget::resizeEvent(QResizeEvent *e) {
- _addContactLnk->move((width() - _addContactLnk->width()) / 2, (st::noContactsHeight + st::noContactsFont->height) / 2);
- _editFilterLnk->move((width() - _editFilterLnk->width()) / 2, (st::noContactsHeight + st::noContactsFont->height) / 2);
+ resizeEmptyLabel();
const auto widthForCancelButton = qMax(width(), st::columnMinimalWidthLeft);
const auto left = widthForCancelButton - st::dialogsSearchInSkip - _cancelSearchInChat->width();
const auto top = (st::dialogsSearchInHeight - st::dialogsCancelSearchInPeer.height) / 2;
@@ -2231,19 +2217,12 @@ void InnerWidget::refresh(bool toTop) {
if (needCollapsedRowsRefresh()) {
return refreshWithCollapsedRows(toTop);
}
+ refreshEmptyLabel();
const auto list = shownDialogs();
- _addContactLnk->setVisible(!_filterId
- && (_state == WidgetState::Default)
- && list->empty()
- && session().data().contactsLoaded().current());
- _editFilterLnk->setVisible((_filterId > 0)
- && (_state == WidgetState::Default)
- && list->empty()
- && session().data().chatsList()->loaded());
auto h = 0;
if (_state == WidgetState::Default) {
if (list->empty()) {
- h = st::noContactsHeight;
+ h = st::dialogsEmptyHeight;
} else {
h = dialogsOffset() + list->size() * DialogsRowHeight();
}
@@ -2266,6 +2245,69 @@ void InnerWidget::refresh(bool toTop) {
update();
}
+void InnerWidget::refreshEmptyLabel() {
+ const auto data = &session().data();
+ const auto state = !shownDialogs()->empty()
+ ? EmptyState::None
+ : (!_filterId && data->contactsLoaded().current())
+ ? EmptyState::NoContacts
+ : (_filterId > 0) && data->chatsList()->loaded()
+ ? EmptyState::EmptyFolder
+ : EmptyState::Loading;
+ if (state == EmptyState::None) {
+ _emptyState = state;
+ _empty.destroy();
+ return;
+ } else if (_emptyState == state) {
+ _empty->setVisible(_state == WidgetState::Default);
+ return;
+ }
+ _emptyState = state;
+ auto phrase = (state == EmptyState::NoContacts)
+ ? tr::lng_no_chats()
+ : (state == EmptyState::EmptyFolder)
+ ? tr::lng_no_chats_filter()
+ : tr::lng_contacts_loading();
+ auto link = (state == EmptyState::NoContacts)
+ ? tr::lng_add_contact_button()
+ : (state == EmptyState::EmptyFolder)
+ ? tr::lng_filters_context_edit()
+ : rpl::single(QString());
+ auto full = rpl::combine(
+ std::move(phrase),
+ std::move(link)
+ ) | rpl::map([](const QString &phrase, const QString &link) {
+ auto result = Ui::Text::WithEntities(phrase);
+ if (!link.isEmpty()) {
+ result.append("\n\n").append(Ui::Text::Link(link));
+ }
+ return result;
+ });
+ _empty.create(this, std::move(full), st::dialogsEmptyLabel);
+ resizeEmptyLabel();
+ _empty->setClickHandlerFilter([=](const auto &...) {
+ if (_emptyState == EmptyState::NoContacts) {
+ App::wnd()->onShowAddContact();
+ } else if (_emptyState == EmptyState::EmptyFolder) {
+ editOpenedFilter();
+ }
+ return false;
+ });
+ _empty->setVisible(_state == WidgetState::Default);
+}
+
+void InnerWidget::resizeEmptyLabel() {
+ if (!_empty) {
+ return;
+ }
+ const auto useWidth = std::min(
+ _empty->naturalWidth(),
+ width() - 2 * st::dialogsEmptySkip);
+ const auto left = (width() - useWidth) / 2;
+ _empty->resizeToWidth(useWidth);
+ _empty->move(left, (st::dialogsEmptyHeight - _empty->height()) / 2);
+}
+
void InnerWidget::clearMouseSelection(bool clearSelection) {
_mouseSelection = false;
_lastMousePosition = std::nullopt;
@@ -2611,6 +2653,7 @@ void InnerWidget::switchToFilter(FilterId filterId) {
_filterId = filterId;
refreshWithCollapsedRows(true);
}
+ refreshEmptyLabel();
}
bool InnerWidget::chooseHashtag() {
@@ -3048,6 +3091,27 @@ void InnerWidget::setupShortcuts() {
return false;
});
+ const auto filters = &session().data().chatsFilters().list();
+ if (const auto filtersCount = int(filters->size())) {
+ auto &&folders = ranges::view::zip(
+ Shortcuts::kShowFolder,
+ ranges::view::ints(0, ranges::unreachable));
+
+ for (const auto [command, index] : folders) {
+ const auto select = (command == Command::ShowFolderLast)
+ ? filtersCount
+ : std::clamp(index, 0, filtersCount);
+ request->check(command) && request->handle([=] {
+ if (select <= filtersCount) {
+ _controller->setActiveChatsFilter((select > 0)
+ ? (*filters)[select - 1].id()
+ : 0);
+ }
+ return true;
+ });
+ }
+ }
+
static const auto kPinned = {
Command::ChatPinned1,
Command::ChatPinned2,
@@ -3076,42 +3140,23 @@ void InnerWidget::setupShortcuts() {
});
}
- auto &&folders = ranges::view::zip(
- Shortcuts::kShowFolder,
- ranges::view::ints(0, ranges::unreachable));
-
- for (const auto [command, index] : folders) {
- request->check(command) && request->handle([=, index = index] {
- const auto list = &session().data().chatsFilters().list();
- if (index >= list->size()) {
- return false;
- }
- const auto filterId = list->at(index).id();
- _controller->setActiveChatsFilter((filterId == _filterId)
- ? 0
- : filterId);
- return true;
- });
- }
-
const auto nearFolder = [=](bool isNext) {
const auto id = _controller->activeChatsFilterCurrent();
const auto list = &session().data().chatsFilters().list();
- const auto it = (id == 0)
- ? begin(*list) - 1
- : ranges::find(*list, id, &Data::ChatFilter::id);
- if (it == end(*list) && id != 0) {
+ const auto index = (id != 0)
+ ? int(ranges::find(*list, id, &Data::ChatFilter::id)
+ - begin(*list))
+ : -1;
+ if (index == list->size() && id != 0) {
return false;
}
- const auto i = isNext ? 1 : -1;
- const auto index = it - begin(*list) + i;
- if (index >= (int)list->size() || index < -1) {
+ const auto changed = index + (isNext ? 1 : -1);
+ if (changed >= int(list->size()) || changed < -1) {
return false;
}
- const auto filterId = (index == -1)
- ? 0
- : list->at(index).id();
- _controller->setActiveChatsFilter(filterId);
+ _controller->setActiveChatsFilter((changed >= 0)
+ ? (*list)[changed].id()
+ : 0);
return true;
};
diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h
index 0669ecee5..f46265770 100644
--- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h
+++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h
@@ -22,7 +22,7 @@ class Session;
namespace Ui {
class IconButton;
class PopupMenu;
-class LinkButton;
+class FlatLabel;
} // namespace Ui
namespace Window {
@@ -97,6 +97,8 @@ public:
void clearFilter();
void refresh(bool toTop = false);
+ void refreshEmptyLabel();
+ void resizeEmptyLabel();
bool chooseRow();
@@ -168,6 +170,13 @@ private:
NextOrOriginal,
};
+ enum class EmptyState : uchar {
+ None,
+ Loading,
+ NoContacts,
+ EmptyFolder,
+ };
+
Main::Session &session() const;
void dialogRowReplaced(Row *oldRow, Row *newRow);
@@ -357,6 +366,7 @@ private:
int _filteredPressed = -1;
bool _waitingForSearch = false;
+ EmptyState _emptyState = EmptyState::None;
QString _peerSearchQuery;
std::vector> _peerSearchResults;
@@ -376,8 +386,7 @@ private:
WidgetState _state = WidgetState::Default;
- object_ptr _addContactLnk;
- object_ptr _editFilterLnk;
+ object_ptr _empty = { nullptr };
object_ptr _cancelSearchInChat;
object_ptr _cancelSearchFromUser;
diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp
index d1d0bcb43..fa69e0a9d 100644
--- a/Telegram/SourceFiles/history/history.cpp
+++ b/Telegram/SourceFiles/history/history.cpp
@@ -1948,12 +1948,6 @@ void History::setFolderPointer(Data::Folder *folder) {
const auto wasInList = inChatList();
if (wasInList) {
removeFromChatList(0, owner().chatsList(this->folder()));
- for (const auto &filter : filters.list()) {
- const auto id = filter.id();
- if (inChatList(id)) {
- removeFromChatList(id, filters.chatsList(id));
- }
- }
}
const auto was = _folder.value_or(nullptr);
_folder = folder;
@@ -1962,12 +1956,10 @@ void History::setFolderPointer(Data::Folder *folder) {
}
if (wasInList) {
addToChatList(0, owner().chatsList(folder));
- for (const auto &filter : filters.list()) {
- if (filter.contains(this)) {
- const auto id = filter.id();
- addToChatList(id, filters.chatsList(id));
- }
- }
+
+ owner().chatsFilters().refreshHistory(this);
+ updateChatListEntry();
+
owner().chatsListChanged(was);
owner().chatsListChanged(folder);
} else if (!wasKnown) {
diff --git a/Telegram/build/version b/Telegram/build/version
index b6e9151e0..7b16f3e18 100644
--- a/Telegram/build/version
+++ b/Telegram/build/version
@@ -1,7 +1,7 @@
-AppVersion 2000000
+AppVersion 2000001
AppVersionStrMajor 2.0
-AppVersionStrSmall 2.0
-AppVersionStr 2.0.0
+AppVersionStrSmall 2.0.1
+AppVersionStr 2.0.1
BetaChannel 0
AlphaVersion 0
-AppVersionOriginal 2.0
+AppVersionOriginal 2.0.1
diff --git a/Telegram/lib_ui b/Telegram/lib_ui
index d443119c7..4a2a5d0ff 160000
--- a/Telegram/lib_ui
+++ b/Telegram/lib_ui
@@ -1 +1 @@
-Subproject commit d443119c7c5629cb87fd8b062941c25a6bc5abab
+Subproject commit 4a2a5d0ff1aea9aa860c56a90558463caf82aa55
diff --git a/changelog.txt b/changelog.txt
index 5d85a0ba8..398c8ad0a 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,3 +1,9 @@
+2.0.1 (31.03.20)
+
+- Switch between folders using Ctrl+1, ..., Ctrl+8.
+- Fix crash when a pinned in folder chat was added to archive.
+- Fix font issues in Linux version.
+
2.0 (30.03.20)
- Organize chats into Chat Folders if you have too many chats.