diff --git a/Telegram/Resources/animations/no_chats.tgs b/Telegram/Resources/animations/no_chats.tgs
new file mode 100644
index 0000000000..a30673b48a
Binary files /dev/null and b/Telegram/Resources/animations/no_chats.tgs differ
diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings
index d8566d25f5..cfeb51a1eb 100644
--- a/Telegram/Resources/langs/lang.strings
+++ b/Telegram/Resources/langs/lang.strings
@@ -434,6 +434,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_dlg_new_channel_name" = "Channel name";
"lng_dlg_new_bot_name" = "Bot name";
"lng_no_chats" = "Your chats will be here";
+"lng_no_conversations" = "You have no\nconversations yet.";
+"lng_no_conversations_button" = "New Message";
+"lng_no_conversations_subtitle" = "Your contacts on Telegram";
"lng_no_chats_filter" = "No chats currently belong to this folder.";
"lng_no_saved_sublists" = "You can save messages from other chats here.";
"lng_contacts_loading" = "Loading...";
diff --git a/Telegram/Resources/qrc/telegram/animations.qrc b/Telegram/Resources/qrc/telegram/animations.qrc
index 9beaa522d3..cc9c2313ed 100644
--- a/Telegram/Resources/qrc/telegram/animations.qrc
+++ b/Telegram/Resources/qrc/telegram/animations.qrc
@@ -38,6 +38,7 @@
../../animations/edit_peers/topics_tabs.tgs
../../animations/edit_peers/topics_list.tgs
../../animations/edit_peers/direct_messages.tgs
+ ../../animations/no_chats.tgs
../../animations/dice/dice_idle.tgs
../../animations/dice/dart_idle.tgs
diff --git a/Telegram/SourceFiles/dialogs/dialogs.style b/Telegram/SourceFiles/dialogs/dialogs.style
index babbf4027a..b3e2eceea0 100644
--- a/Telegram/SourceFiles/dialogs/dialogs.style
+++ b/Telegram/SourceFiles/dialogs/dialogs.style
@@ -244,6 +244,17 @@ dialogsEmptyLabel: FlatLabel(defaultFlatLabel) {
align: align(top);
textFg: windowSubTextFg;
}
+dialogEmptyButton: RoundButton(defaultActiveButton) {
+}
+dialogEmptyButtonSkip: 12px;
+dialogEmptyButtonLabel: FlatLabel(defaultFlatLabel) {
+ style: TextStyle(defaultTextStyle) {
+ font: font(boxFontSize semibold);
+ }
+ minWidth: 32px;
+ align: align(top);
+ textFg: windowFg;
+}
dialogsMenuToggle: IconButton {
width: 40px;
diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp
index 85e395cdb8..e812c8173a 100644
--- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp
+++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp
@@ -31,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/text/text_utilities.h"
#include "ui/text/text_options.h"
#include "ui/dynamic_thumbnails.h"
+#include "ui/vertical_list.h"
#include "ui/painter.h"
#include "ui/rect.h"
#include "ui/ui_utility.h"
@@ -58,8 +59,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/options.h"
#include "lang/lang_keys.h"
#include "lottie/lottie_icon.h"
-#include "mainwindow.h"
-#include "mainwidget.h"
+#include "settings/settings_common.h"
#include "storage/storage_account.h"
#include "apiwrap.h"
#include "main/main_session.h"
@@ -80,6 +80,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_chat_filters.h"
#include "base/qt/qt_common_adapters.h"
#include "styles/style_dialogs.h"
+#include "styles/style_boxes.h"
#include "styles/style_chat.h" // popupMenuExpandedSeparator
#include "styles/style_chat_helpers.h"
#include "styles/style_color_indices.h"
@@ -4075,9 +4076,18 @@ void InnerWidget::refreshEmpty() {
if (state == EmptyState::None) {
_emptyState = state;
_empty.destroy();
+ _emptyList.destroy();
+ _emptyButton.destroy();
return;
} else if (_emptyState == state) {
_empty->setVisible(_state == WidgetState::Default);
+ if (_emptyList) {
+ _emptyList->setVisible(_state == WidgetState::Default);
+ _empty->setVisible(!_emptyList->isVisible());
+ }
+ if (_emptyButton) {
+ _emptyButton->setVisible(_state == WidgetState::Default);
+ }
return;
}
_emptyState = state;
@@ -4108,7 +4118,6 @@ void InnerWidget::refreshEmpty() {
return result;
});
_empty.create(this, std::move(full), st::dialogsEmptyLabel);
- resizeEmpty();
_empty->overrideLinkClickHandler([=] {
if (_emptyState == EmptyState::NoContacts) {
_controller->showAddContact();
@@ -4120,6 +4129,58 @@ void InnerWidget::refreshEmpty() {
}
});
_empty->setVisible(_state == WidgetState::Default);
+
+ if (state == EmptyState::NoContacts) {
+ const auto isListVisible = _state == WidgetState::Default;
+ _emptyList.create(this);
+ _emptyList->setVisible(isListVisible);
+
+ auto icon = ::Settings::CreateLottieIcon(
+ _emptyList,
+ {
+ .name = u"no_chats"_q,
+ .sizeOverride = Size(st::changePhoneIconSize),
+ });
+ const auto iconWidget = _emptyList->add(
+ object_ptr>(_emptyList, std::move(icon.widget)));
+ Ui::AddSkip(_emptyList);
+ const auto label = _emptyList->add(
+ object_ptr(
+ _emptyList,
+ tr::lng_no_conversations(),
+ st::dialogEmptyButtonLabel));
+ if (_state == WidgetState::Default) {
+ icon.animate(anim::repeat::once);
+ }
+ _emptyButton.create(
+ this,
+ tr::lng_no_conversations_button(),
+ st::dialogEmptyButton);
+ _emptyButton->setTextTransform(
+ Ui::RoundButton::TextTransform::NoTransform);
+ _emptyButton->setVisible(isListVisible);
+ _emptyButton->setClickedCallback([=, window = _controller] {
+ window->show(PrepareContactsBox(window));
+ });
+ geometryValue() | rpl::start_with_next([=](const QRect &r) {
+ const auto top = r.height()
+ - _emptyButton->height()
+ - st::dialogEmptyButtonSkip;
+ _emptyButton->moveToLeft(st::dialogEmptyButtonSkip, top);
+ }, _emptyButton->lifetime());
+ geometryValue() | rpl::start_with_next([=](const QRect &r) {
+ const auto bottom = _emptyButton
+ ? (_emptyButton->height() + st::dialogEmptyButtonSkip)
+ : 0;
+ _emptyList->moveToLeft(
+ 0,
+ ((r.height() - bottom) - _emptyList->height()) / 2);
+ }, _emptyList->lifetime());
+
+ _empty->setVisible(!_emptyList->isVisible());
+ }
+
+ resizeEmpty();
}
void InnerWidget::resizeEmpty() {
@@ -4128,6 +4189,13 @@ void InnerWidget::resizeEmpty() {
_empty->resizeToWidth(width() - 2 * skip);
_empty->move(skip, (st::dialogsEmptyHeight - _empty->height()) / 2);
}
+ if (_emptyList) {
+ _emptyList->resizeToWidth(width());
+ }
+ if (_emptyButton) {
+ const auto skip = st::dialogEmptyButtonSkip;
+ _emptyButton->resizeToWidth(width() - 2 * skip);
+ }
if (_searchEmpty) {
_searchEmpty->resizeToWidth(width());
_searchEmpty->move(0, searchedOffset());
diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h
index c3c4a6b033..e54955ee2e 100644
--- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h
+++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h
@@ -43,6 +43,8 @@ namespace Ui {
class IconButton;
class PopupMenu;
class FlatLabel;
+class VerticalLayout;
+class RoundButton;
struct ScrollToRequest;
namespace Controls {
enum class QuickDialogAction;
@@ -619,6 +621,8 @@ private:
object_ptr _searchEmpty = { nullptr };
SearchState _searchEmptyState;
object_ptr _empty = { nullptr };
+ object_ptr _emptyList = { nullptr };
+ object_ptr _emptyButton = { nullptr };
Ui::DraggingScrollManager _draggingScroll;