Indicate other accounts unread messages.
Before Width: | Height: | Size: 110 B After Width: | Height: | Size: 128 B |
Before Width: | Height: | Size: 148 B After Width: | Height: | Size: 247 B |
Before Width: | Height: | Size: 190 B After Width: | Height: | Size: 350 B |
BIN
Telegram/Resources/icons/dialogs_menu_unread.png
Normal file
After Width: | Height: | Size: 146 B |
BIN
Telegram/Resources/icons/dialogs_menu_unread@2x.png
Normal file
After Width: | Height: | Size: 289 B |
BIN
Telegram/Resources/icons/dialogs_menu_unread@3x.png
Normal file
After Width: | Height: | Size: 386 B |
BIN
Telegram/Resources/icons/dialogs_menu_unread_dot.png
Normal file
After Width: | Height: | Size: 170 B |
BIN
Telegram/Resources/icons/dialogs_menu_unread_dot@2x.png
Normal file
After Width: | Height: | Size: 362 B |
BIN
Telegram/Resources/icons/dialogs_menu_unread_dot@3x.png
Normal file
After Width: | Height: | Size: 488 B |
|
@ -101,7 +101,7 @@ dialogsMenuToggle: IconButton {
|
|||
|
||||
icon: icon {{ "dialogs_menu", dialogsMenuIconFg }};
|
||||
iconOver: icon {{ "dialogs_menu", dialogsMenuIconFgOver }};
|
||||
iconPosition: point(10px, 10px);
|
||||
iconPosition: point(-1px, -1px);
|
||||
|
||||
rippleAreaPosition: point(0px, 0px);
|
||||
rippleAreaSize: 40px;
|
||||
|
@ -109,6 +109,15 @@ dialogsMenuToggle: IconButton {
|
|||
color: windowBgOver;
|
||||
}
|
||||
}
|
||||
dialogsMenuToggleUnread: icon {
|
||||
{ "dialogs_menu_unread", dialogsMenuIconFg },
|
||||
{ "dialogs_menu_unread_dot", dialogsUnreadBg },
|
||||
};
|
||||
dialogsMenuToggleUnreadMuted: icon {
|
||||
{ "dialogs_menu_unread", dialogsMenuIconFg },
|
||||
{ "dialogs_menu_unread_dot", dialogsMenuIconFg },
|
||||
};
|
||||
|
||||
dialogsLock: IconButton(dialogsMenuToggle) {
|
||||
icon: icon {{ "dialogs_lock", dialogsMenuIconFg }};
|
||||
iconOver: icon {{ "dialogs_lock", dialogsMenuIconFgOver }};
|
||||
|
|
|
@ -32,6 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "window/window_session_controller.h"
|
||||
#include "window/window_slide_animation.h"
|
||||
#include "window/window_connecting_widget.h"
|
||||
#include "window/window_main_menu.h"
|
||||
#include "storage/storage_media_prepare.h"
|
||||
#include "storage/storage_account.h"
|
||||
#include "data/data_session.h"
|
||||
|
@ -274,17 +275,9 @@ Widget::Widget(
|
|||
Core::App().lockByPasscode();
|
||||
_lockUnlock->setIconOverride(nullptr);
|
||||
});
|
||||
rpl::single(
|
||||
rpl::empty_value()
|
||||
) | rpl::then(
|
||||
controller->filtersMenuChanged()
|
||||
) | rpl::start_with_next([=] {
|
||||
const auto filtersHidden = !controller->filtersWidth();
|
||||
_mainMenuToggle->setVisible(filtersHidden);
|
||||
_searchForNarrowFilters->setVisible(!filtersHidden);
|
||||
updateControlsGeometry();
|
||||
}, lifetime());
|
||||
_mainMenuToggle->setClickedCallback([=] { showMainMenu(); });
|
||||
|
||||
setupMainMenuToggle();
|
||||
|
||||
_searchForNarrowFilters->setClickedCallback([=] { Ui::showChatsList(&session()); });
|
||||
|
||||
_chooseByDragTimer.setSingleShot(true);
|
||||
|
@ -426,6 +419,31 @@ void Widget::setupSupportMode() {
|
|||
) | rpl::to_empty);
|
||||
}
|
||||
|
||||
void Widget::setupMainMenuToggle() {
|
||||
_mainMenuToggle->setClickedCallback([=] { showMainMenu(); });
|
||||
|
||||
rpl::single(
|
||||
rpl::empty_value()
|
||||
) | rpl::then(
|
||||
controller()->filtersMenuChanged()
|
||||
) | rpl::start_with_next([=] {
|
||||
const auto filtersHidden = !controller()->filtersWidth();
|
||||
_mainMenuToggle->setVisible(filtersHidden);
|
||||
_searchForNarrowFilters->setVisible(!filtersHidden);
|
||||
updateControlsGeometry();
|
||||
}, lifetime());
|
||||
|
||||
Window::OtherAccountsUnreadState(
|
||||
) | rpl::start_with_next([=](const Window::OthersUnreadState &state) {
|
||||
const auto icon = !state.count
|
||||
? nullptr
|
||||
: !state.allMuted
|
||||
? &st::dialogsMenuToggleUnread
|
||||
: &st::dialogsMenuToggleUnreadMuted;
|
||||
_mainMenuToggle->setIconOverride(icon, icon);
|
||||
}, _mainMenuToggle->lifetime());
|
||||
}
|
||||
|
||||
void Widget::fullSearchRefreshOn(rpl::producer<> events) {
|
||||
std::move(
|
||||
events
|
||||
|
|
|
@ -139,6 +139,7 @@ private:
|
|||
|
||||
void setupSupportMode();
|
||||
void setupConnectingWidget();
|
||||
void setupMainMenuToggle();
|
||||
bool searchForPeersRequired(const QString &query) const;
|
||||
void setSearchInChat(Key chat, UserData *from = nullptr);
|
||||
void showJumpToDate();
|
||||
|
|
|
@ -285,6 +285,14 @@ windowFiltersMainMenu: SideBarButton(windowFiltersButton) {
|
|||
iconPosition: point(-1px, -1px);
|
||||
minHeight: 54px;
|
||||
}
|
||||
windowFiltersMainMenuUnread: icon {
|
||||
{ "dialogs_menu_unread", sideBarIconFg },
|
||||
{ "dialogs_menu_unread_dot", sideBarBadgeBg },
|
||||
};
|
||||
windowFiltersMainMenuUnreadMuted: icon {
|
||||
{ "dialogs_menu_unread", sideBarIconFg },
|
||||
{ "dialogs_menu_unread_dot", sideBarBadgeBgMuted },
|
||||
};
|
||||
windowFilterSmallItem: PeerListItem(defaultPeerListItem) {
|
||||
height: 44px;
|
||||
photoPosition: point(15px, 5px);
|
||||
|
|
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "mainwindow.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "window/window_controller.h"
|
||||
#include "window/window_main_menu.h"
|
||||
#include "main/main_session.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_chat_filters.h"
|
||||
|
@ -75,6 +76,8 @@ FiltersMenu::FiltersMenu(
|
|||
FiltersMenu::~FiltersMenu() = default;
|
||||
|
||||
void FiltersMenu::setup() {
|
||||
setupMainMenuIcon();
|
||||
|
||||
_outer.setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
_outer.show();
|
||||
_outer.paintRequest(
|
||||
|
@ -134,6 +137,18 @@ void FiltersMenu::setup() {
|
|||
});
|
||||
}
|
||||
|
||||
void FiltersMenu::setupMainMenuIcon() {
|
||||
OtherAccountsUnreadState(
|
||||
) | rpl::start_with_next([=](const OthersUnreadState &state) {
|
||||
const auto icon = !state.count
|
||||
? nullptr
|
||||
: !state.allMuted
|
||||
? &st::windowFiltersMainMenuUnread
|
||||
: &st::windowFiltersMainMenuUnreadMuted;
|
||||
_menu.setIconOverride(icon, icon);
|
||||
}, _outer.lifetime());
|
||||
}
|
||||
|
||||
void FiltersMenu::scrollToButton(not_null<Ui::RpWidget*> widget) {
|
||||
const auto globalPosition = widget->mapToGlobal(QPoint(0, 0));
|
||||
const auto localTop = _scroll.mapFromGlobal(globalPosition).y();
|
||||
|
|
|
@ -46,6 +46,7 @@ private:
|
|||
FilterId id,
|
||||
const QString &title,
|
||||
Ui::FilterIcon icon);
|
||||
void setupMainMenuIcon();
|
||||
void showMenu(QPoint position, FilterId id);
|
||||
void showEditBox(FilterId id);
|
||||
void showRemoveBox(FilterId id);
|
||||
|
|
|
@ -433,27 +433,13 @@ void MainMenu::ToggleAccountsButton::validateUnreadBadge() {
|
|||
}
|
||||
|
||||
QString MainMenu::ToggleAccountsButton::computeUnreadBadge() const {
|
||||
const auto active = &Core::App().activeAccount();
|
||||
auto allMuted = true;
|
||||
for (const auto &[index, account] : Core::App().domain().accounts()) {
|
||||
if (account.get() == active) {
|
||||
continue;
|
||||
} else if (const auto session = account->maybeSession()) {
|
||||
if (!session->data().unreadBadgeMuted()) {
|
||||
allMuted = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (allMuted) {
|
||||
return QString();
|
||||
}
|
||||
const auto count = Core::App().unreadBadge()
|
||||
- active->session().data().unreadBadge();
|
||||
return (count > 99)
|
||||
const auto state = OtherAccountsUnreadStateCurrent();
|
||||
return state.allMuted
|
||||
? QString()
|
||||
: (state.count > 99)
|
||||
? u"99+"_q
|
||||
: (count > 0)
|
||||
? QString::number(count)
|
||||
: (state.count > 0)
|
||||
? QString::number(state.count)
|
||||
: QString();
|
||||
}
|
||||
|
||||
|
@ -1135,4 +1121,33 @@ void MainMenu::initResetScaleButton() {
|
|||
}, lifetime());
|
||||
}
|
||||
|
||||
OthersUnreadState OtherAccountsUnreadStateCurrent() {
|
||||
auto &app = Core::App();
|
||||
const auto active = &app.activeAccount();
|
||||
auto allMuted = true;
|
||||
for (const auto &[index, account] : app.domain().accounts()) {
|
||||
if (account.get() == active) {
|
||||
continue;
|
||||
} else if (const auto session = account->maybeSession()) {
|
||||
if (!session->data().unreadBadgeMuted()) {
|
||||
allMuted = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
.count = (app.unreadBadge() - active->session().data().unreadBadge()),
|
||||
.allMuted = allMuted,
|
||||
};
|
||||
}
|
||||
|
||||
rpl::producer<OthersUnreadState> OtherAccountsUnreadState() {
|
||||
return rpl::single(
|
||||
rpl::empty_value()
|
||||
) | rpl::then(
|
||||
Core::App().unreadBadgeChanges()
|
||||
) | rpl::map(OtherAccountsUnreadStateCurrent);
|
||||
}
|
||||
|
||||
|
||||
} // namespace Window
|
||||
|
|
|
@ -99,4 +99,12 @@ private:
|
|||
|
||||
};
|
||||
|
||||
struct OthersUnreadState {
|
||||
int count = 0;
|
||||
bool allMuted = false;
|
||||
};
|
||||
|
||||
[[nodiscard]] OthersUnreadState OtherAccountsUnreadStateCurrent();
|
||||
[[nodiscard]] rpl::producer<OthersUnreadState> OtherAccountsUnreadState();
|
||||
|
||||
} // namespace Window
|
||||
|
|