[Option][GUI] Compact chat list

This commit is contained in:
Eric Kotato 2022-08-26 22:26:26 +03:00
parent 6ed812fa13
commit 53014877c1
9 changed files with 554 additions and 229 deletions

View file

@ -33,6 +33,7 @@
"ktg_settings_sticker_scale_both_about": "When enabled, sticker maximum width will be changed along with sticker height.",
"ktg_settings_emoji_outline": "Big emoji outline",
"ktg_settings_always_show_scheduled": "Always show scheduled",
"ktg_settings_chat_list_compact": "Compact chat list",
"ktg_fonts_title": "Fonts",
"ktg_settings_fonts": "Change application fonts",
"ktg_fonts_reset": "Reset",

View file

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "dialogs/dialogs_inner_widget.h"
#include "kotato/kotato_settings.h"
#include "dialogs/dialogs_indexed_list.h"
#include "dialogs/ui/dialogs_layout.h"
#include "dialogs/dialogs_widget.h"
@ -62,6 +63,18 @@ namespace {
constexpr auto kHashtagResultsLimit = 5;
constexpr auto kStartReorderThreshold = 30;
inline int DialogsRowHeight() {
return (::Kotato::JsonSettings::GetInt("chat_list_lines") == 1
? st::dialogsImportantBarHeight
: st::dialogsRowHeight);
}
inline int DialogsPhotoSize() {
return (::Kotato::JsonSettings::GetInt("chat_list_lines") == 1
? st::dialogsUnreadHeight
: st::dialogsPhotoSize);
}
int FixedOnTopDialogsCount(not_null<Dialogs::IndexedList*> list) {
auto result = 0;
for (const auto &row : *list) {
@ -200,6 +213,12 @@ InnerWidget::InnerWidget(
refresh();
}, lifetime());
::Kotato::JsonSettings::Events(
"chat_list_lines"
) | rpl::start_with_next([=] {
refresh();
}, lifetime());
session().changes().historyUpdates(
Data::HistoryUpdate::Flag::IsPinned
| Data::HistoryUpdate::Flag::ChatOccupied
@ -289,7 +308,10 @@ void InnerWidget::refreshWithCollapsedRows(bool toTop) {
? (*list->begin())->folder()
: nullptr;
const auto inMainMenu = session().settings().archiveInMainMenu();
if (archive && (session().settings().archiveCollapsed() || inMainMenu)) {
if (archive &&
(session().settings().archiveCollapsed()
|| inMainMenu
|| ::Kotato::JsonSettings::GetInt("chat_list_lines") == 1)) {
if (_selected && _selected->folder() == archive) {
_selected = nullptr;
}
@ -318,7 +340,7 @@ void InnerWidget::refreshWithCollapsedRows(bool toTop) {
int InnerWidget::dialogsOffset() const {
return _collapsedRows.size() * st::dialogsImportantBarHeight
- _skipTopDialogs * st::dialogsRowHeight;
- _skipTopDialogs * DialogsRowHeight();
}
int InnerWidget::fixedOnTopCount() const {
@ -334,7 +356,7 @@ int InnerWidget::fixedOnTopCount() const {
}
int InnerWidget::pinnedOffset() const {
return dialogsOffset() + fixedOnTopCount() * st::dialogsRowHeight;
return dialogsOffset() + fixedOnTopCount() * DialogsRowHeight();
}
int InnerWidget::filteredOffset() const {
@ -342,11 +364,11 @@ int InnerWidget::filteredOffset() const {
}
int InnerWidget::peerSearchOffset() const {
return filteredOffset() + (_filterResults.size() * st::dialogsRowHeight) + st::searchedBarHeight;
return filteredOffset() + (_filterResults.size() * DialogsRowHeight()) + st::searchedBarHeight;
}
int InnerWidget::searchedOffset() const {
auto result = peerSearchOffset() + (_peerSearchResults.empty() ? 0 : ((_peerSearchResults.size() * st::dialogsRowHeight) + st::searchedBarHeight));
auto result = peerSearchOffset() + (_peerSearchResults.empty() ? 0 : ((_peerSearchResults.size() * DialogsRowHeight()) + st::searchedBarHeight));
if (_searchInChat) {
result += searchInChatSkip();
}
@ -396,7 +418,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
const auto rows = shownDialogs();
const auto &list = rows->all();
const auto otherStart = std::max(int(rows->size()) - _skipTopDialogs, 0) * st::dialogsRowHeight;
const auto otherStart = std::max(int(rows->size()) - _skipTopDialogs, 0) * DialogsRowHeight();
const auto active = activeEntry.key;
const auto selected = _menuRow.key
? _menuRow.key
@ -411,7 +433,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
const auto skip = dialogsOffset();
auto reorderingPinned = (_aboveIndex >= 0 && !_pinnedRows.empty());
if (reorderingPinned) {
dialogsClip = dialogsClip.marginsAdded(QMargins(0, st::dialogsRowHeight, 0, st::dialogsRowHeight));
dialogsClip = dialogsClip.marginsAdded(QMargins(0, DialogsRowHeight(), 0, DialogsRowHeight()));
}
const auto promoted = fixedOnTopCount();
@ -440,7 +462,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
}
};
auto i = list.cfind(dialogsClip.top() - skip, st::dialogsRowHeight);
auto i = list.cfind(dialogsClip.top() - skip, DialogsRowHeight());
while (i != list.cend() && (*i)->pos() < _skipTopDialogs) {
++i;
}
@ -449,13 +471,13 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
// If we're reordering pinned chats we need to fill this area background first.
if (reorderingPinned) {
p.fillRect(0, (promoted - _skipTopDialogs) * st::dialogsRowHeight, fullWidth, st::dialogsRowHeight * _pinnedRows.size(), st::dialogsBg);
p.fillRect(0, (promoted - _skipTopDialogs) * DialogsRowHeight(), fullWidth, DialogsRowHeight() * _pinnedRows.size(), st::dialogsBg);
}
p.translate(0, (lastPaintedPos - _skipTopDialogs) * st::dialogsRowHeight);
p.translate(0, (lastPaintedPos - _skipTopDialogs) * DialogsRowHeight());
for (auto e = list.cend(); i != e; ++i) {
auto row = (*i);
if ((lastPaintedPos - _skipTopDialogs) * st::dialogsRowHeight >= dialogsClip.top() - skip + dialogsClip.height()) {
if ((lastPaintedPos - _skipTopDialogs) * DialogsRowHeight() >= dialogsClip.top() - skip + dialogsClip.height()) {
break;
}
@ -465,7 +487,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
paintDialog(row);
}
p.translate(0, st::dialogsRowHeight);
p.translate(0, DialogsRowHeight());
++lastPaintedPos;
}
@ -474,9 +496,9 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
auto i = list.cfind(promoted + _aboveIndex, 1);
auto pos = (i == list.cend()) ? -1 : (*i)->pos();
if (pos == promoted + _aboveIndex) {
p.translate(0, (pos - lastPaintedPos) * st::dialogsRowHeight);
p.translate(0, (pos - lastPaintedPos) * DialogsRowHeight());
paintDialog(*i);
p.translate(0, (lastPaintedPos - pos) * st::dialogsRowHeight);
p.translate(0, (lastPaintedPos - pos) * DialogsRowHeight());
}
}
}
@ -531,9 +553,9 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
}
if (!_filterResults.empty()) {
auto skip = filteredOffset();
auto from = floorclamp(r.y() - skip, st::dialogsRowHeight, 0, _filterResults.size());
auto to = ceilclamp(r.y() + r.height() - skip, st::dialogsRowHeight, 0, _filterResults.size());
p.translate(0, from * st::dialogsRowHeight);
auto from = floorclamp(r.y() - skip, DialogsRowHeight(), 0, _filterResults.size());
auto to = ceilclamp(r.y() + r.height() - skip, DialogsRowHeight(), 0, _filterResults.size());
p.translate(0, from * DialogsRowHeight());
if (from < _filterResults.size()) {
for (; from < to; ++from) {
const auto row = _filterResults[from];
@ -553,7 +575,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
active,
selected,
ms);
p.translate(0, st::dialogsRowHeight);
p.translate(0, DialogsRowHeight());
}
}
}
@ -566,9 +588,9 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
p.translate(0, st::searchedBarHeight);
auto skip = peerSearchOffset();
auto from = floorclamp(r.y() - skip, st::dialogsRowHeight, 0, _peerSearchResults.size());
auto to = ceilclamp(r.y() + r.height() - skip, st::dialogsRowHeight, 0, _peerSearchResults.size());
p.translate(0, from * st::dialogsRowHeight);
auto from = floorclamp(r.y() - skip, DialogsRowHeight(), 0, _peerSearchResults.size());
auto to = ceilclamp(r.y() + r.height() - skip, DialogsRowHeight(), 0, _peerSearchResults.size());
p.translate(0, from * DialogsRowHeight());
if (from < _peerSearchResults.size()) {
const auto activePeer = activeEntry.key.peer();
for (; from < to; ++from) {
@ -582,7 +604,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
? _peerSearchPressed
: _peerSearchSelected));
paintPeerSearchResult(p, result.get(), fullWidth, active, selected);
p.translate(0, st::dialogsRowHeight);
p.translate(0, DialogsRowHeight());
}
}
}
@ -625,9 +647,9 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
p.translate(0, st::searchedBarHeight);
auto skip = searchedOffset();
auto from = floorclamp(r.y() - skip, st::dialogsRowHeight, 0, _searchResults.size());
auto to = ceilclamp(r.y() + r.height() - skip, st::dialogsRowHeight, 0, _searchResults.size());
p.translate(0, from * st::dialogsRowHeight);
auto from = floorclamp(r.y() - skip, DialogsRowHeight(), 0, _searchResults.size());
auto to = ceilclamp(r.y() + r.height() - skip, DialogsRowHeight(), 0, _searchResults.size());
p.translate(0, from * DialogsRowHeight());
if (from < _searchResults.size()) {
for (; from < to; ++from) {
const auto &result = _searchResults[from];
@ -645,7 +667,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
selected,
ms,
showUnreadInSearchResults);
p.translate(0, st::dialogsRowHeight);
p.translate(0, DialogsRowHeight());
}
}
}
@ -707,7 +729,7 @@ void InnerWidget::paintPeerSearchResult(
int fullWidth,
bool active,
bool selected) const {
QRect fullRect(0, 0, fullWidth, st::dialogsRowHeight);
QRect fullRect(0, 0, fullWidth, DialogsRowHeight());
p.fillRect(fullRect, active ? st::dialogsBgActive : (selected ? st::dialogsBgOver : st::dialogsBg));
if (!active) {
result->row.paintRipple(p, 0, 0, fullWidth);
@ -715,11 +737,17 @@ void InnerWidget::paintPeerSearchResult(
auto peer = result->peer;
auto userpicPeer = (peer->migrateTo() ? peer->migrateTo() : peer);
userpicPeer->paintUserpicLeft(p, result->row.userpicView(), st::dialogsPadding.x(), st::dialogsPadding.y(), width(), st::dialogsPhotoSize);
userpicPeer->paintUserpicLeft(p, result->row.userpicView(), st::dialogsPadding.x(), st::dialogsPadding.y(), width(), DialogsPhotoSize());
auto nameleft = st::dialogsPadding.x() + st::dialogsPhotoSize + st::dialogsPhotoPadding;
auto nameleft = st::dialogsPadding.x() + DialogsPhotoSize() + st::dialogsPhotoPadding;
auto namewidth = fullWidth - nameleft - st::dialogsPadding.x();
QRect rectForName(nameleft, st::dialogsPadding.y() + st::dialogsNameTop, namewidth, st::msgNameFont->height);
QRect rectForName(
nameleft,
(::Kotato::JsonSettings::GetInt("chat_list_lines") == 1)
? st::dialogsPadding.y()
: st::dialogsPadding.y() + st::dialogsNameTop,
namewidth,
st::msgNameFont->height);
// draw chat icon
if (auto chatTypeIcon = Ui::ChatTypeIcon(peer, active, selected)) {
@ -746,29 +774,43 @@ void InnerWidget::paintPeerSearchResult(
badgeStyle);
rectForName.setWidth(rectForName.width() - badgeWidth);
QRect tr(nameleft, st::dialogsPadding.y() + st::msgNameFont->height + st::dialogsSkip, namewidth, st::dialogsTextFont->height);
p.setFont(st::dialogsTextFont);
QString username = peer->userName();
if (!active && username.startsWith(_peerSearchQuery, Qt::CaseInsensitive)) {
auto first = '@' + username.mid(0, _peerSearchQuery.size());
auto second = username.mid(_peerSearchQuery.size());
auto w = st::dialogsTextFont->width(first);
if (w >= tr.width()) {
p.setPen(st::dialogsTextFgService);
p.drawText(tr.left(), tr.top() + st::dialogsTextFont->ascent, st::dialogsTextFont->elided(first, tr.width()));
} else {
p.setPen(st::dialogsTextFgService);
p.drawText(tr.left(), tr.top() + st::dialogsTextFont->ascent, first);
p.setPen(st::dialogsTextFg);
p.drawText(tr.left() + w, tr.top() + st::dialogsTextFont->ascent, st::dialogsTextFont->elided(second, tr.width() - w));
}
} else {
p.setPen(active ? st::dialogsTextFgActive : st::dialogsTextFgService);
p.drawText(tr.left(), tr.top() + st::dialogsTextFont->ascent, st::dialogsTextFont->elided('@' + username, tr.width()));
}
if (::Kotato::JsonSettings::GetInt("chat_list_lines") == 1) {
QString text = peer->nameText().toString();
p.setPen(active
? st::dialogsNameFgActive
: selected
? st::dialogsNameFgOver
: st::dialogsNameFg);
p.setFont(st::dialogsTextFont);
p.setPen(active ? st::dialogsTextFgActive : st::dialogsNameFg);
peer->nameText().drawElided(p, rectForName.left(), rectForName.top(), rectForName.width());
Ui::Text::String textStr;
textStr.setText(st::dialogsTextStyle, text, Ui::NameTextOptions());
textStr.drawElided(p, rectForName.left(), rectForName.top(), rectForName.width());
} else {
QRect tr(nameleft, st::dialogsPadding.y() + st::msgNameFont->height + st::dialogsSkip, namewidth, st::dialogsTextFont->height);
p.setFont(st::dialogsTextFont);
QString username = peer->userName();
if (!active && username.startsWith(_peerSearchQuery, Qt::CaseInsensitive)) {
auto first = '@' + username.mid(0, _peerSearchQuery.size());
auto second = username.mid(_peerSearchQuery.size());
auto w = st::dialogsTextFont->width(first);
if (w >= tr.width()) {
p.setPen(st::dialogsTextFgService);
p.drawText(tr.left(), tr.top() + st::dialogsTextFont->ascent, st::dialogsTextFont->elided(first, tr.width()));
} else {
p.setPen(st::dialogsTextFgService);
p.drawText(tr.left(), tr.top() + st::dialogsTextFont->ascent, first);
p.setPen(st::dialogsTextFg);
p.drawText(tr.left() + w, tr.top() + st::dialogsTextFont->ascent, st::dialogsTextFont->elided(second, tr.width() - w));
}
} else {
p.setPen(active ? st::dialogsTextFgActive : st::dialogsTextFgService);
p.drawText(tr.left(), tr.top() + st::dialogsTextFont->ascent, st::dialogsTextFont->elided('@' + username, tr.width()));
}
p.setPen(active ? st::dialogsTextFgActive : st::dialogsNameFg);
peer->nameText().drawElided(p, rectForName.left(), rectForName.top(), rectForName.width());
}
}
void InnerWidget::paintSearchInChat(Painter &p) const {
@ -930,7 +972,7 @@ void InnerWidget::selectByMouse(QPoint globalPosition) {
: (mouseY >= offset)
? shownDialogs()->rowAtY(
mouseY - offset,
st::dialogsRowHeight)
DialogsRowHeight())
: nullptr;
if (_selected != selected || _collapsedSelected != collapsedSelected) {
updateSelectedRow();
@ -961,7 +1003,7 @@ void InnerWidget::selectByMouse(QPoint globalPosition) {
}
if (!_filterResults.empty()) {
auto skip = filteredOffset();
auto filteredSelected = (mouseY >= skip) ? ((mouseY - skip) / st::dialogsRowHeight) : -1;
auto filteredSelected = (mouseY >= skip) ? ((mouseY - skip) / DialogsRowHeight()) : -1;
if (filteredSelected < 0 || filteredSelected >= _filterResults.size()) {
filteredSelected = -1;
}
@ -973,7 +1015,7 @@ void InnerWidget::selectByMouse(QPoint globalPosition) {
}
if (!_peerSearchResults.empty()) {
auto skip = peerSearchOffset();
auto peerSearchSelected = (mouseY >= skip) ? ((mouseY - skip) / st::dialogsRowHeight) : -1;
auto peerSearchSelected = (mouseY >= skip) ? ((mouseY - skip) / DialogsRowHeight()) : -1;
if (peerSearchSelected < 0 || peerSearchSelected >= _peerSearchResults.size()) {
peerSearchSelected = -1;
}
@ -985,7 +1027,7 @@ void InnerWidget::selectByMouse(QPoint globalPosition) {
}
if (!_waitingForSearch && !_searchResults.empty()) {
auto skip = searchedOffset();
auto searchedSelected = (mouseY >= skip) ? ((mouseY - skip) / st::dialogsRowHeight) : -1;
auto searchedSelected = (mouseY >= skip) ? ((mouseY - skip) / DialogsRowHeight()) : -1;
if (searchedSelected < 0 || searchedSelected >= _searchResults.size()) {
searchedSelected = -1;
}
@ -1019,7 +1061,7 @@ void InnerWidget::mousePressEvent(QMouseEvent *e) {
});
} else if (_pressed) {
auto row = _pressed;
row->addRipple(e->pos() - QPoint(0, dialogsOffset() + _pressed->pos() * st::dialogsRowHeight), QSize(width(), st::dialogsRowHeight), [this, row] {
row->addRipple(e->pos() - QPoint(0, dialogsOffset() + _pressed->pos() * DialogsRowHeight()), QSize(width(), DialogsRowHeight()), [this, row] {
if (!_pinnedShiftAnimation.animating()) {
row->entry()->updateChatListEntry();
}
@ -1035,19 +1077,19 @@ void InnerWidget::mousePressEvent(QMouseEvent *e) {
const auto filterId = _filterId;
row->addRipple(
e->pos() - QPoint(0, filteredOffset() + _filteredPressed * st::dialogsRowHeight),
QSize(width(), st::dialogsRowHeight),
QSize(width(), DialogsRowHeight()),
[=] { repaintDialogRow(filterId, row); });
} else if (base::in_range(_peerSearchPressed, 0, _peerSearchResults.size())) {
auto &result = _peerSearchResults[_peerSearchPressed];
auto row = &result->row;
row->addRipple(
e->pos() - QPoint(0, peerSearchOffset() + _peerSearchPressed * st::dialogsRowHeight),
QSize(width(), st::dialogsRowHeight),
e->pos() - QPoint(0, peerSearchOffset() + _peerSearchPressed * DialogsRowHeight()),
QSize(width(), DialogsRowHeight()),
[this, peer = result->peer] { updateSearchResult(peer); });
} else if (base::in_range(_searchedPressed, 0, _searchResults.size())) {
auto &row = _searchResults[_searchedPressed];
row->addRipple(e->pos() - QPoint(0, searchedOffset() + _searchedPressed * st::dialogsRowHeight), QSize(width(), st::dialogsRowHeight), [this, index = _searchedPressed] {
rtlupdate(0, searchedOffset() + index * st::dialogsRowHeight, width(), st::dialogsRowHeight);
row->addRipple(e->pos() - QPoint(0, searchedOffset() + _searchedPressed * DialogsRowHeight()), QSize(width(), DialogsRowHeight()), [this, index = _searchedPressed] {
rtlupdate(0, searchedOffset() + index * DialogsRowHeight(), width(), DialogsRowHeight());
});
}
if (anim::Disabled()
@ -1175,7 +1217,7 @@ bool InnerWidget::updateReorderPinned(QPoint localPosition) {
auto yaddWas = _pinnedRows[_draggingIndex].yadd.current();
auto shift = 0;
auto now = crl::now();
auto rowHeight = st::dialogsRowHeight;
auto rowHeight = DialogsRowHeight();
if (_dragStart.y() > localPosition.y() && _draggingIndex > 0) {
shift = -floorclamp(_dragStart.y() - localPosition.y() + (rowHeight / 2), rowHeight, 0, _draggingIndex);
@ -1255,11 +1297,11 @@ bool InnerWidget::pinnedShiftAnimationCallback(crl::time now) {
}
if (updateMin >= 0) {
auto top = pinnedOffset();
auto updateFrom = top + st::dialogsRowHeight * (updateMin - 1);
auto updateHeight = st::dialogsRowHeight * (updateMax - updateMin + 3);
auto updateFrom = top + DialogsRowHeight() * (updateMin - 1);
auto updateHeight = DialogsRowHeight() * (updateMax - updateMin + 3);
if (base::in_range(_aboveIndex, 0, _pinnedRows.size())) {
// Always include currently dragged chat in its current and old positions.
auto aboveRowBottom = top + (_aboveIndex + 1) * st::dialogsRowHeight;
auto aboveRowBottom = top + (_aboveIndex + 1) * DialogsRowHeight();
auto aboveTopShift = qCeil(_pinnedRows[_aboveIndex].yadd.current());
accumulate_max(updateHeight, (aboveRowBottom - updateFrom) + _aboveTopShift);
accumulate_max(updateHeight, (aboveRowBottom - updateFrom) + aboveTopShift);
@ -1421,7 +1463,7 @@ void InnerWidget::handleChatListEntryRefreshes() {
) | rpl::filter([=](const Event &event) {
return (event.filterId == _filterId);
}) | rpl::start_with_next([=](const Event &event) {
const auto rowHeight = st::dialogsRowHeight;
const auto rowHeight = DialogsRowHeight();
const auto from = dialogsOffset() + event.moved.from * rowHeight;
const auto to = dialogsOffset() + event.moved.to * rowHeight;
const auto &key = event.key;
@ -1482,7 +1524,7 @@ int InnerWidget::defaultRowTop(not_null<Row*> row) const {
if (base::in_range(position, 0, _pinnedRows.size())) {
top += qRound(_pinnedRows[position].yadd.current());
}
return top + position * st::dialogsRowHeight;
return top + position * DialogsRowHeight();
}
void InnerWidget::repaintDialogRow(
@ -1493,7 +1535,7 @@ void InnerWidget::repaintDialogRow(
if (const auto folder = row->folder()) {
repaintCollapsedFolderRow(folder);
}
update(0, defaultRowTop(row), width(), st::dialogsRowHeight);
update(0, defaultRowTop(row), width(), DialogsRowHeight());
}
} else if (_state == WidgetState::Filtered) {
if (!filterId) {
@ -1501,9 +1543,9 @@ void InnerWidget::repaintDialogRow(
if (_filterResults[i]->key() == row->key()) {
update(
0,
filteredOffset() + i * st::dialogsRowHeight,
filteredOffset() + i * DialogsRowHeight(),
width(),
st::dialogsRowHeight);
DialogsRowHeight());
break;
}
}
@ -1532,7 +1574,7 @@ void InnerWidget::updateSearchResult(not_null<PeerData*> peer) {
auto index = 0, add = peerSearchOffset();
for (const auto &result : _peerSearchResults) {
if (result->peer == peer) {
rtlupdate(0, add + index * st::dialogsRowHeight, width(), st::dialogsRowHeight);
rtlupdate(0, add + index * DialogsRowHeight(), width(), DialogsRowHeight());
break;
}
++index;
@ -1546,7 +1588,7 @@ void InnerWidget::updateDialogRow(
QRect updateRect,
UpdateRowSections sections) {
if (updateRect.isEmpty()) {
updateRect = QRect(0, 0, width(), st::dialogsRowHeight);
updateRect = QRect(0, 0, width(), DialogsRowHeight());
}
if (IsServerMsgId(-row.fullId.msg)) {
if (const auto peer = row.key.peer()) {
@ -1578,7 +1620,7 @@ void InnerWidget::updateDialogRow(
if (base::in_range(position, 0, _pinnedRows.size())) {
top += qRound(_pinnedRows[position].yadd.current());
}
updateRow(top + position * st::dialogsRowHeight);
updateRow(top + position * DialogsRowHeight());
}
}
} else if (_state == WidgetState::Filtered) {
@ -1588,7 +1630,7 @@ void InnerWidget::updateDialogRow(
auto index = 0;
for (const auto result : _filterResults) {
if (result->key() == row.key) {
updateRow(add + index * st::dialogsRowHeight);
updateRow(add + index * DialogsRowHeight());
break;
}
++index;
@ -1601,7 +1643,7 @@ void InnerWidget::updateDialogRow(
auto index = 0;
for (const auto &result : _peerSearchResults) {
if (result->peer == peer) {
updateRow(add + index * st::dialogsRowHeight);
updateRow(add + index * DialogsRowHeight());
break;
}
++index;
@ -1614,7 +1656,7 @@ void InnerWidget::updateDialogRow(
auto index = 0;
for (const auto &result : _searchResults) {
if (isSearchResultActive(result.get(), row)) {
updateRow(add + index * st::dialogsRowHeight);
updateRow(add + index * DialogsRowHeight());
break;
}
++index;
@ -1639,9 +1681,9 @@ void InnerWidget::updateSelectedRow(Key key) {
if (base::in_range(position, 0, _pinnedRows.size())) {
top += qRound(_pinnedRows[position].yadd.current());
}
update(0, top + position * st::dialogsRowHeight, width(), st::dialogsRowHeight);
update(0, top + position * DialogsRowHeight(), width(), DialogsRowHeight());
} else if (_selected) {
update(0, dialogsOffset() + _selected->pos() * st::dialogsRowHeight, width(), st::dialogsRowHeight);
update(0, dialogsOffset() + _selected->pos() * DialogsRowHeight(), width(), DialogsRowHeight());
} else if (_collapsedSelected >= 0) {
update(0, _collapsedSelected * st::dialogsImportantBarHeight, width(), st::dialogsImportantBarHeight);
}
@ -1649,18 +1691,18 @@ void InnerWidget::updateSelectedRow(Key key) {
if (key) {
for (auto i = 0, l = int(_filterResults.size()); i != l; ++i) {
if (_filterResults[i]->key() == key) {
update(0, filteredOffset() + i * st::dialogsRowHeight, width(), st::dialogsRowHeight);
update(0, filteredOffset() + i * DialogsRowHeight(), width(), DialogsRowHeight());
break;
}
}
} else if (_hashtagSelected >= 0) {
update(0, _hashtagSelected * st::mentionHeight, width(), st::mentionHeight);
} else if (_filteredSelected >= 0) {
update(0, filteredOffset() + _filteredSelected * st::dialogsRowHeight, width(), st::dialogsRowHeight);
update(0, filteredOffset() + _filteredSelected * DialogsRowHeight(), width(), DialogsRowHeight());
} else if (_peerSearchSelected >= 0) {
update(0, peerSearchOffset() + _peerSearchSelected * st::dialogsRowHeight, width(), st::dialogsRowHeight);
update(0, peerSearchOffset() + _peerSearchSelected * DialogsRowHeight(), width(), DialogsRowHeight());
} else if (_searchedSelected >= 0) {
update(0, searchedOffset() + _searchedSelected * st::dialogsRowHeight, width(), st::dialogsRowHeight);
update(0, searchedOffset() + _searchedSelected * DialogsRowHeight(), width(), DialogsRowHeight());
}
}
}
@ -2151,7 +2193,8 @@ bool InnerWidget::needCollapsedRowsRefresh() const {
const auto collapsedHasArchive = !_collapsedRows.empty()
&& (_collapsedRows.back()->folder != nullptr);
const auto archiveIsCollapsed = (archive != nullptr)
&& session().settings().archiveCollapsed();
&& (session().settings().archiveCollapsed()
|| ::Kotato::JsonSettings::GetInt("chat_list_lines") == 1);
const auto archiveIsInMainMenu = (archive != nullptr)
&& session().settings().archiveInMainMenu();
return archiveIsInMainMenu
@ -2178,13 +2221,13 @@ void InnerWidget::refresh(bool toTop) {
if (list->empty()) {
h = st::dialogsEmptyHeight;
} else {
h = dialogsOffset() + list->size() * st::dialogsRowHeight;
h = dialogsOffset() + list->size() * DialogsRowHeight();
}
} else if (_state == WidgetState::Filtered) {
if (_waitingForSearch) {
h = searchedOffset() + (_searchResults.size() * st::dialogsRowHeight) + ((_searchResults.empty() && !_searchInChat) ? -st::searchedBarHeight : 0);
h = searchedOffset() + (_searchResults.size() * DialogsRowHeight()) + ((_searchResults.empty() && !_searchInChat) ? -st::searchedBarHeight : 0);
} else {
h = searchedOffset() + (_searchResults.size() * st::dialogsRowHeight);
h = searchedOffset() + (_searchResults.size() * DialogsRowHeight());
}
}
resize(width(), h);
@ -2414,8 +2457,8 @@ void InnerWidget::selectSkip(int32 direction) {
if (_collapsedSelected >= 0 || _selected) {
const auto fromY = (_collapsedSelected >= 0)
? (_collapsedSelected * st::dialogsImportantBarHeight)
: (dialogsOffset() + _selected->pos() * st::dialogsRowHeight);
mustScrollTo(fromY, fromY + st::dialogsRowHeight);
: (dialogsOffset() + _selected->pos() * DialogsRowHeight());
mustScrollTo(fromY, fromY + DialogsRowHeight());
}
} else if (_state == WidgetState::Filtered) {
if (_hashtagResults.empty() && _filterResults.empty() && _peerSearchResults.empty() && _searchResults.empty()) {
@ -2466,11 +2509,11 @@ void InnerWidget::selectSkip(int32 direction) {
if (base::in_range(_hashtagSelected, 0, _hashtagResults.size())) {
mustScrollTo(_hashtagSelected * st::mentionHeight, (_hashtagSelected + 1) * st::mentionHeight);
} else if (base::in_range(_filteredSelected, 0, _filterResults.size())) {
mustScrollTo(filteredOffset() + _filteredSelected * st::dialogsRowHeight, filteredOffset() + (_filteredSelected + 1) * st::dialogsRowHeight);
mustScrollTo(filteredOffset() + _filteredSelected * DialogsRowHeight(), filteredOffset() + (_filteredSelected + 1) * DialogsRowHeight());
} else if (base::in_range(_peerSearchSelected, 0, _peerSearchResults.size())) {
mustScrollTo(peerSearchOffset() + _peerSearchSelected * st::dialogsRowHeight + (_peerSearchSelected ? 0 : -st::searchedBarHeight), peerSearchOffset() + (_peerSearchSelected + 1) * st::dialogsRowHeight);
mustScrollTo(peerSearchOffset() + _peerSearchSelected * DialogsRowHeight() + (_peerSearchSelected ? 0 : -st::searchedBarHeight), peerSearchOffset() + (_peerSearchSelected + 1) * DialogsRowHeight());
} else {
mustScrollTo(searchedOffset() + _searchedSelected * st::dialogsRowHeight + (_searchedSelected ? 0 : -st::searchedBarHeight), searchedOffset() + (_searchedSelected + 1) * st::dialogsRowHeight);
mustScrollTo(searchedOffset() + _searchedSelected * DialogsRowHeight() + (_searchedSelected ? 0 : -st::searchedBarHeight), searchedOffset() + (_searchedSelected + 1) * DialogsRowHeight());
}
}
update();
@ -2480,33 +2523,33 @@ void InnerWidget::scrollToEntry(const RowDescriptor &entry) {
int32 fromY = -1;
if (_state == WidgetState::Default) {
if (auto row = shownDialogs()->getRow(entry.key)) {
fromY = dialogsOffset() + row->pos() * st::dialogsRowHeight;
fromY = dialogsOffset() + row->pos() * DialogsRowHeight();
}
} else if (_state == WidgetState::Filtered) {
for (int32 i = 0, c = _searchResults.size(); i < c; ++i) {
if (isSearchResultActive(_searchResults[i].get(), entry)) {
fromY = searchedOffset() + i * st::dialogsRowHeight;
fromY = searchedOffset() + i * DialogsRowHeight();
break;
}
}
if (fromY < 0) {
for (auto i = 0, c = int(_filterResults.size()); i != c; ++i) {
if (_filterResults[i]->key() == entry.key) {
fromY = filteredOffset() + (i * st::dialogsRowHeight);
fromY = filteredOffset() + (i * DialogsRowHeight());
break;
}
}
}
}
if (fromY >= 0) {
mustScrollTo(fromY, fromY + st::dialogsRowHeight);
mustScrollTo(fromY, fromY + DialogsRowHeight());
}
}
void InnerWidget::selectSkipPage(int32 pixels, int32 direction) {
clearMouseSelection();
const auto list = shownDialogs();
int toSkip = pixels / int(st::dialogsRowHeight);
int toSkip = pixels / int(DialogsRowHeight());
if (_state == WidgetState::Default) {
if (!_selected) {
if (direction > 0 && list->size() > _skipTopDialogs) {
@ -2532,8 +2575,8 @@ void InnerWidget::selectSkipPage(int32 pixels, int32 direction) {
if (_collapsedSelected >= 0 || _selected) {
const auto fromY = (_collapsedSelected >= 0)
? (_collapsedSelected * st::dialogsImportantBarHeight)
: (dialogsOffset() + _selected->pos() * st::dialogsRowHeight);
mustScrollTo(fromY, fromY + st::dialogsRowHeight);
: (dialogsOffset() + _selected->pos() * DialogsRowHeight());
mustScrollTo(fromY, fromY + DialogsRowHeight());
}
} else {
return selectSkip(direction * toSkip);
@ -2548,10 +2591,10 @@ void InnerWidget::loadPeerPhotos() {
auto yFrom = _visibleTop;
auto yTo = _visibleTop + (_visibleBottom - _visibleTop) * (PreloadHeightsCount + 1);
if (_state == WidgetState::Default) {
auto otherStart = list->size() * st::dialogsRowHeight;
auto otherStart = list->size() * DialogsRowHeight();
if (yFrom < otherStart) {
for (auto i = list->cfind(yFrom, st::dialogsRowHeight), end = list->cend(); i != end; ++i) {
if (((*i)->pos() * st::dialogsRowHeight) >= yTo) {
for (auto i = list->cfind(yFrom, DialogsRowHeight()), end = list->cend(); i != end; ++i) {
if (((*i)->pos() * DialogsRowHeight()) >= yTo) {
break;
}
(*i)->entry()->loadUserpic();
@ -2562,10 +2605,10 @@ void InnerWidget::loadPeerPhotos() {
}
yTo -= otherStart;
} else if (_state == WidgetState::Filtered) {
int32 from = (yFrom - filteredOffset()) / st::dialogsRowHeight;
int32 from = (yFrom - filteredOffset()) / DialogsRowHeight();
if (from < 0) from = 0;
if (from < _filterResults.size()) {
int32 to = (yTo / int32(st::dialogsRowHeight)) + 1;
int32 to = (yTo / int32(DialogsRowHeight())) + 1;
if (to > _filterResults.size()) to = _filterResults.size();
for (; from < to; ++from) {
@ -2573,20 +2616,20 @@ void InnerWidget::loadPeerPhotos() {
}
}
from = (yFrom > filteredOffset() + st::searchedBarHeight ? ((yFrom - filteredOffset() - st::searchedBarHeight) / int32(st::dialogsRowHeight)) : 0) - _filterResults.size();
from = (yFrom > filteredOffset() + st::searchedBarHeight ? ((yFrom - filteredOffset() - st::searchedBarHeight) / int32(DialogsRowHeight())) : 0) - _filterResults.size();
if (from < 0) from = 0;
if (from < _peerSearchResults.size()) {
int32 to = (yTo > filteredOffset() + st::searchedBarHeight ? ((yTo - filteredOffset() - st::searchedBarHeight) / int32(st::dialogsRowHeight)) : 0) - _filterResults.size() + 1;
int32 to = (yTo > filteredOffset() + st::searchedBarHeight ? ((yTo - filteredOffset() - st::searchedBarHeight) / int32(DialogsRowHeight())) : 0) - _filterResults.size() + 1;
if (to > _peerSearchResults.size()) to = _peerSearchResults.size();
for (; from < to; ++from) {
_peerSearchResults[from]->peer->loadUserpic();
}
}
from = (yFrom > filteredOffset() + ((_peerSearchResults.empty() ? 0 : st::searchedBarHeight) + st::searchedBarHeight) ? ((yFrom - filteredOffset() - (_peerSearchResults.empty() ? 0 : st::searchedBarHeight) - st::searchedBarHeight) / int32(st::dialogsRowHeight)) : 0) - _filterResults.size() - _peerSearchResults.size();
from = (yFrom > filteredOffset() + ((_peerSearchResults.empty() ? 0 : st::searchedBarHeight) + st::searchedBarHeight) ? ((yFrom - filteredOffset() - (_peerSearchResults.empty() ? 0 : st::searchedBarHeight) - st::searchedBarHeight) / int32(DialogsRowHeight())) : 0) - _filterResults.size() - _peerSearchResults.size();
if (from < 0) from = 0;
if (from < _searchResults.size()) {
int32 to = (yTo > filteredOffset() + (_peerSearchResults.empty() ? 0 : st::searchedBarHeight) + st::searchedBarHeight ? ((yTo - filteredOffset() - (_peerSearchResults.empty() ? 0 : st::searchedBarHeight) - st::searchedBarHeight) / int32(st::dialogsRowHeight)) : 0) - _filterResults.size() - _peerSearchResults.size() + 1;
int32 to = (yTo > filteredOffset() + (_peerSearchResults.empty() ? 0 : st::searchedBarHeight) + st::searchedBarHeight ? ((yTo - filteredOffset() - (_peerSearchResults.empty() ? 0 : st::searchedBarHeight) - st::searchedBarHeight) / int32(DialogsRowHeight())) : 0) - _filterResults.size() - _peerSearchResults.size() + 1;
if (to > _searchResults.size()) to = _searchResults.size();
for (; from < to; ++from) {
@ -2953,8 +2996,8 @@ void InnerWidget::updateDialogRowCornerStatus(not_null<History*> history) {
? st::dialogsOnlineBadgeSkip
: st::dialogsCallBadgeSkip;
const auto updateRect = QRect(
st::dialogsPhotoSize - skip.x() - size,
st::dialogsPhotoSize - skip.y() - size,
DialogsPhotoSize() - skip.x() - size,
DialogsPhotoSize() - skip.y() - size,
size,
size
).marginsAdded(
@ -3014,11 +3057,11 @@ void InnerWidget::updateRowCornerStatusShown(
[](not_null<Row*> row) { return row->history(); });
const auto index = (i - begin(_filterResults));
const auto row = (i == end(_filterResults)) ? nullptr : i->get();
return { row, filteredOffset() + index * st::dialogsRowHeight };
return { row, filteredOffset() + index * DialogsRowHeight() };
};
if (const auto &[row, top] = findRow(history); row != nullptr) {
const auto visible = (top < _visibleBottom)
&& (top + st::dialogsRowHeight > _visibleTop);
&& (top + DialogsRowHeight() > _visibleTop);
row->updateCornerBadgeShown(
history->peer,
visible ? Fn<void()>(crl::guard(this, repaint)) : nullptr);

View file

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "dialogs/dialogs_row.h"
#include "kotato/kotato_settings.h"
#include "ui/effects/ripple_animation.h"
#include "ui/text/text_options.h"
#include "ui/text/text_utilities.h"
@ -148,6 +149,9 @@ void BasicRow::updateCornerBadgeShown(
not_null<PeerData*> peer,
Fn<void()> updateCallback) const {
const auto shown = [&] {
if (::Kotato::JsonSettings::GetInt("chat_list_lines") == 1) {
return false;
}
if (const auto user = peer->asUser()) {
return Data::IsUserOnline(user);
} else if (const auto channel = peer->asChannel()) {
@ -177,7 +181,9 @@ void BasicRow::PaintCornerBadgeFrame(
view,
0,
0,
st::dialogsPhotoSize);
(::Kotato::JsonSettings::GetInt("chat_list_lines") == 1
? st::dialogsUnreadHeight
: st::dialogsPhotoSize));
PainterHighQualityEnabler hq(q);
q.setCompositionMode(QPainter::CompositionMode_Source);
@ -224,7 +230,9 @@ void BasicRow::paintUserpic(
st::dialogsPadding.x(),
st::dialogsPadding.y(),
fullWidth,
st::dialogsPhotoSize);
(::Kotato::JsonSettings::GetInt("chat_list_lines") == 1
? st::dialogsUnreadHeight
: st::dialogsPhotoSize));
if (!historyForCornerBadge || !_cornerBadgeShown) {
_cornerBadgeUserpic = nullptr;
}
@ -232,9 +240,10 @@ void BasicRow::paintUserpic(
}
ensureCornerBadgeUserpic();
if (_cornerBadgeUserpic->frame.isNull()) {
_cornerBadgeUserpic->frame = QImage(
st::dialogsPhotoSize * cRetinaFactor(),
st::dialogsPhotoSize * cRetinaFactor(),
const auto frameSize = (::Kotato::JsonSettings::GetInt("chat_list_lines") == 1
? st::dialogsUnreadHeight
: st::dialogsPhotoSize) * cRetinaFactor();
_cornerBadgeUserpic->frame = QImage(frameSize, frameSize,
QImage::Format_ARGB32_Premultiplied);
_cornerBadgeUserpic->frame.setDevicePixelRatio(cRetinaFactor());
}

View file

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "dialogs/dialogs_widget.h"
#include "kotato/kotato_settings.h"
#include "kotato/kotato_lang.h"
#include "dialogs/dialogs_inner_widget.h"
#include "dialogs/dialogs_search_from_controllers.h"
@ -1602,7 +1603,7 @@ void Widget::updateControlsGeometry() {
_forwardCancel->moveToLeft(0, filterAreaTop);
filterAreaTop += st::dialogsForwardHeight;
}
auto smallLayoutWidth = (st::dialogsPadding.x() + st::dialogsPhotoSize + st::dialogsPadding.x());
auto smallLayoutWidth = (st::dialogsPadding.x() + (::Kotato::JsonSettings::GetInt("chat_list_lines") == 1 ? st::dialogsUnreadHeight : st::dialogsPhotoSize) + st::dialogsPadding.x());
auto smallLayoutRatio = (width() < st::columnMinimalWidthLeft) ? (st::columnMinimalWidthLeft - width()) / float64(st::columnMinimalWidthLeft - smallLayoutWidth) : 0.;
auto filterLeft = (controller()->filtersWidth() ? st::dialogsFilterSkip : st::dialogsFilterPadding.x() + _mainMenuToggle->width()) + st::dialogsFilterPadding.x();
auto filterRight = (session().domain().local().hasLocalPasscode() ? (st::dialogsFilterPadding.x() + _lockUnlock->width()) : st::dialogsFilterSkip) + st::dialogsFilterPadding.x();
@ -1838,7 +1839,7 @@ void Widget::onCancelSearchInChat() {
void Widget::onDialogMoved(int movedFrom, int movedTo) {
int32 st = _scroll->scrollTop();
if (st > movedTo && st < movedFrom) {
_scroll->scrollToY(st + st::dialogsRowHeight);
_scroll->scrollToY(st + (::Kotato::JsonSettings::GetInt("chat_list_lines") == 1 ? st::dialogsImportantBarHeight : st::dialogsRowHeight));
}
}

View file

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "dialogs/ui/dialogs_layout.h"
#include "kotato/kotato_settings.h"
#include "data/data_abstract_structure.h"
#include "data/data_drafts.h"
#include "data/data_session.h"
@ -90,7 +91,8 @@ void PaintNarrowCounter(
bool selected,
bool active,
bool unreadMuted,
bool mentionOrReactionMuted) {
bool mentionOrReactionMuted,
int lines = 2) {
auto skipBeforeMention = 0;
if (displayUnreadCounter || displayUnreadMark) {
const auto counter = (unreadCount > 0)
@ -102,9 +104,11 @@ void PaintNarrowCounter(
: 3;
const auto unreadRight = st::dialogsPadding.x()
+ st::dialogsPhotoSize;
const auto unreadTop = st::dialogsPadding.y()
+ st::dialogsPhotoSize
- st::dialogsUnreadHeight;
const auto unreadTop = (lines == 1
? st::dialogsPadding.y()
: st::dialogsPadding.y()
+ st::dialogsPhotoSize
- st::dialogsUnreadHeight);
UnreadBadgeStyle st;
st.active = active;
@ -122,11 +126,15 @@ void PaintNarrowCounter(
if (displayMentionBadge || displayReactionBadge) {
const auto counter = QString();
const auto unreadRight = st::dialogsPadding.x()
+ st::dialogsPhotoSize
+ (::Kotato::JsonSettings::GetInt("chat_list_lines") == 1
? st::dialogsUnreadHeight
: st::dialogsPhotoSize)
- skipBeforeMention;
const auto unreadTop = st::dialogsPadding.y()
+ st::dialogsPhotoSize
- st::dialogsUnreadHeight;
const auto unreadTop = (lines == 1
? st::dialogsPadding.y()
: st::dialogsPadding.y()
+ st::dialogsPhotoSize
- st::dialogsUnreadHeight);
UnreadBadgeStyle st;
st.active = active;
@ -298,6 +306,186 @@ enum class Flag {
};
inline constexpr bool is_flag_type(Flag) { return true; }
template <typename PaintItemCallback, typename PaintCounterCallback>
void paintOneLineRow(
Painter &p,
not_null<const BasicRow*> row,
not_null<Entry*> entry,
Dialogs::Key chat,
FilterId filterId,
PeerData *from,
const HiddenSenderInfo *hiddenSenderInfo,
HistoryItem *item,
const Data::Draft *draft,
QDateTime date,
int fullWidth,
base::flags<Flag> flags,
crl::time ms,
PaintItemCallback &&paintItemCallback,
PaintCounterCallback &&paintCounterCallback) {
const auto supportMode = entry->session().supportMode();
if (supportMode) {
draft = nullptr;
}
auto active = (flags & Flag::Active);
auto selected = (flags & Flag::Selected);
auto fullRect = QRect(0, 0, fullWidth, st::dialogsImportantBarHeight);
auto bg = active
? st::dialogsBgActive
: (selected
? st::dialogsBgOver
: st::dialogsBg);
auto ripple = active
? st::dialogsRippleBgActive
: st::dialogsRippleBg;
p.fillRect(fullRect, bg);
row->paintRipple(p, 0, 0, fullWidth, &ripple->c);
const auto history = chat.history();
if (flags & Flag::SavedMessages) {
Ui::EmptyUserpic::PaintSavedMessages(
p,
st::dialogsPadding.x(),
st::dialogsPadding.y(),
fullWidth,
st::dialogsUnreadHeight);
} else if (flags & Flag::RepliesMessages) {
Ui::EmptyUserpic::PaintRepliesMessages(
p,
st::dialogsPadding.x(),
st::dialogsPadding.y(),
fullWidth,
st::dialogsUnreadHeight);
} else if (from) {
row->paintUserpic(
p,
from,
(flags & Flag::AllowUserOnline) ? history : nullptr,
ms,
active,
fullWidth);
} else if (hiddenSenderInfo) {
hiddenSenderInfo->userpic.paint(
p,
st::dialogsPadding.x(),
st::dialogsPadding.y(),
fullWidth,
st::dialogsUnreadHeight);
} else {
entry->paintUserpicLeft(
p,
row->userpicView(),
st::dialogsPadding.x(),
st::dialogsPadding.y(),
fullWidth,
st::dialogsUnreadHeight);
}
auto nameleft = st::dialogsPadding.x() * 2 + st::dialogsUnreadHeight;
if (fullWidth <= nameleft) {
if (!draft && item && !item->isEmpty()) {
paintCounterCallback();
}
return;
}
auto namewidth = fullWidth - nameleft - st::dialogsPadding.x();
auto rectForName = QRect(
nameleft,
st::dialogsPadding.y(),
namewidth,
st::dialogsTextFont->height);
const auto promoted = (history && history->useTopPromotion())
&& !(flags & (Flag::SearchResult/* | Flag::FeedSearchResult*/)); // #feed
if (promoted) {
const auto text = tr::lng_proxy_sponsor(tr::now);
PaintRowTopRight(p, text, rectForName, active, selected);
} else if (from && !(flags & Flag::SearchResult/* | Flag::FeedSearchResult*/)) { // #feed
if (const auto chatTypeIcon = ChatTypeIcon(from, active, selected)) {
chatTypeIcon->paint(p, rectForName.topLeft(), fullWidth);
rectForName.setLeft(rectForName.left() + st::dialogsChatTypeSkip);
}
//} else if (const auto feed = chat.feed()) { // #feed
// if (const auto feedTypeIcon = FeedTypeIcon(feed, active, selected)) {
// feedTypeIcon->paint(p, rectForName.topLeft(), fullWidth);
// rectForName.setLeft(rectForName.left() + st::dialogsChatTypeSkip);
// }
}
if (!draft
&& !(supportMode
&& entry->session().supportHelper().isOccupiedBySomeone(history))
&& item
&& !item->isEmpty()) {
const auto nameWithoutCounterWidth = paintItemCallback(nameleft, (flags & Flag::SearchResult ? namewidth : rectForName.width()));
rectForName.setWidth(nameWithoutCounterWidth - st::dialogsPadding.x());
} else if (entry->isPinnedDialog(filterId) && (filterId || !entry->fixedOnTopIndex())) {
auto &icon = (active ? st::dialogsPinnedIconActive : (selected ? st::dialogsPinnedIconOver : st::dialogsPinnedIcon));
icon.paint(p, fullWidth - st::dialogsPadding.x() - icon.width(), st::dialogsPadding.y(), fullWidth);
rectForName.setWidth(rectForName.width() - icon.width() - st::dialogsUnreadPadding);
}
QString text;
if (flags & (Flag::SavedMessages | Flag::RepliesMessages)) {
text = (flags & Flag::SavedMessages)
? tr::lng_saved_messages(tr::now)
: tr::lng_replies_messages(tr::now);
p.setPen(active
? st::dialogsNameFgActive
: selected
? st::dialogsNameFgOver
: st::dialogsNameFg);
} else if (from) {
if (!(flags & Flag::SearchResult)) {
const auto badgeStyle = Ui::PeerBadgeStyle{
(active
? &st::dialogsVerifiedIconActive
: selected
? &st::dialogsVerifiedIconOver
: &st::dialogsVerifiedIcon),
(active
? &st::dialogsScamFgActive
: selected
? &st::dialogsScamFgOver
: &st::dialogsScamFg) };
const auto badgeWidth = Ui::DrawPeerBadgeGetWidth(
from,
p,
rectForName,
from->nameText().maxWidth(),
fullWidth,
badgeStyle);
rectForName.setWidth(rectForName.width() - badgeWidth);
text = from->nameText().toString();
p.setPen(active
? st::dialogsNameFgActive
: selected
? st::dialogsNameFgOver
: st::dialogsNameFg);
p.setFont(st::dialogsTextFont);
}
} else if (hiddenSenderInfo) {
text = hiddenSenderInfo->nameText.toString();
} else {
text = entry->chatListName();
const auto nameFg = active
? st::dialogsNameFgActive
: (selected
? st::dialogsArchiveFgOver
: st::dialogsArchiveFg);
p.setPen(nameFg);
}
if (!(from && (flags & Flag::SearchResult))) {
auto textStr = Ui::Text::String{ st::dialogsTextStyle, text, Ui::NameTextOptions() };
textStr.drawElided(p, rectForName.left(), rectForName.top(), rectForName.width());
}
}
template <typename PaintItemCallback, typename PaintCounterCallback>
void paintRow(
Painter &p,
@ -801,6 +989,11 @@ void RowPainter::paint(
&& history
&& history->unreadReactions().has();
const auto displayUnreadCounter = [&] {
if (fullWidth < st::columnMinimalWidthLeft
&& ::Kotato::JsonSettings::GetInt("chat_list_lines") == 1) {
return false;
}
if (displayMentionBadge
&& unreadCount == 1
&& item
@ -833,9 +1026,12 @@ void RowPainter::paint(
| (peer && peer->isSelf() ? Flag::SavedMessages : Flag(0))
| (peer && peer->isRepliesChat() ? Flag::RepliesMessages : Flag(0));
const auto paintItemCallback = [&](int nameleft, int namewidth) {
const auto texttop = st::dialogsPadding.y()
+ st::msgNameFont->height
+ st::dialogsSkip;
const auto texttop = (::Kotato::JsonSettings::GetInt("chat_list_lines") == 1
? st::dialogsPadding.y()
: st::dialogsPadding.y()
+ st::msgNameFont->height
+ st::dialogsSkip);
const auto availableWidth = PaintWideCounter(
p,
texttop,
@ -851,37 +1047,42 @@ void RowPainter::paint(
selected,
unreadMuted,
mentionOrReactionMuted);
const auto &color = active
? st::dialogsTextFgServiceActive
: (selected
? st::dialogsTextFgServiceOver
: st::dialogsTextFgService);
const auto itemRect = QRect(
nameleft,
texttop,
availableWidth,
st::dialogsTextFont->height);
const auto actionWasPainted = ShowSendActionInDialogs(history)
? history->sendActionPainter()->paint(
p,
itemRect.x(),
itemRect.y(),
itemRect.width(),
fullWidth,
color,
ms)
: false;
if (const auto folder = row->folder()) {
PaintListEntryText(p, itemRect, active, selected, row);
} else if (history && !actionWasPainted) {
history->lastItemDialogsView.paint(
p,
item,
itemRect,
active,
selected,
{});
if (flags & Flag::SearchResult
|| ::Kotato::JsonSettings::GetInt("chat_list_lines") > 1) {
const auto &color = active
? st::dialogsTextFgServiceActive
: (selected
? st::dialogsTextFgServiceOver
: st::dialogsTextFgService);
const auto itemRect = QRect(
nameleft,
texttop,
availableWidth,
st::dialogsTextFont->height);
const auto actionWasPainted = ShowSendActionInDialogs(history)
? history->sendActionPainter()->paint(
p,
itemRect.x(),
itemRect.y(),
itemRect.width(),
fullWidth,
color,
ms)
: false;
if (const auto folder = row->folder()) {
PaintListEntryText(p, itemRect, active, selected, row);
} else if (history && !actionWasPainted) {
history->lastItemDialogsView.paint(
p,
item,
itemRect,
active,
selected,
{});
}
}
return availableWidth;
};
const auto paintCounterCallback = [&] {
PaintNarrowCounter(
@ -894,24 +1095,44 @@ void RowPainter::paint(
selected,
active,
unreadMuted,
mentionOrReactionMuted);
mentionOrReactionMuted,
::Kotato::JsonSettings::GetInt("chat_list_lines"));
};
paintRow(
p,
row,
entry,
row->key(),
filterId,
from,
nullptr,
item,
cloudDraft,
displayDate,
fullWidth,
flags,
ms,
paintItemCallback,
paintCounterCallback);
if (::Kotato::JsonSettings::GetInt("chat_list_lines") == 1) {
paintOneLineRow(
p,
row,
entry,
row->key(),
filterId,
from,
nullptr,
item,
cloudDraft,
displayDate,
fullWidth,
flags,
ms,
paintItemCallback,
paintCounterCallback);
} else {
paintRow(
p,
row,
entry,
row->key(),
filterId,
from,
nullptr,
item,
cloudDraft,
displayDate,
fullWidth,
flags,
ms,
paintItemCallback,
paintCounterCallback);
}
}
void RowPainter::paint(
@ -973,11 +1194,21 @@ void RowPainter::paint(
&& !displayMentionBadge
&& unreadMark;
const auto displayPinnedIcon = false;
const auto showSavedMessages = history->peer->isSelf()
&& !row->searchInChat();
const auto showRepliesMessages = history->peer->isRepliesChat()
&& !row->searchInChat();
const auto flags = (active ? Flag::Active : Flag(0))
| (selected ? Flag::Selected : Flag(0))
| Flag::SearchResult
| (showSavedMessages ? Flag::SavedMessages : Flag(0))
| (showRepliesMessages ? Flag::RepliesMessages : Flag(0));
const auto paintItemCallback = [&](int nameleft, int namewidth) {
const auto texttop = st::dialogsPadding.y()
+ st::msgNameFont->height
+ st::dialogsSkip;
const auto texttop = (::Kotato::JsonSettings::GetInt("chat_list_lines") == 1
? st::dialogsPadding.y()
: st::dialogsPadding.y()
+ st::msgNameFont->height
+ st::dialogsSkip);
const auto availableWidth = PaintWideCounter(
p,
texttop,
@ -994,18 +1225,23 @@ void RowPainter::paint(
unreadMuted,
mentionOrReactionMuted);
const auto itemRect = QRect(
nameleft,
texttop,
availableWidth,
st::dialogsTextFont->height);
row->itemView().paint(
p,
item,
itemRect,
active,
selected,
previewOptions);
if (flags & Flag::SearchResult
|| ::Kotato::JsonSettings::GetInt("chat_list_lines") > 1) {
const auto itemRect = QRect(
nameleft,
texttop,
availableWidth,
st::dialogsTextFont->height);
row->itemView().paint(
p,
item,
itemRect,
active,
selected,
previewOptions);
}
return availableWidth;
};
const auto paintCounterCallback = [&] {
PaintNarrowCounter(
@ -1018,33 +1254,44 @@ void RowPainter::paint(
selected,
active,
unreadMuted,
mentionOrReactionMuted);
mentionOrReactionMuted,
::Kotato::JsonSettings::GetInt("chat_list_lines"));
};
const auto showSavedMessages = history->peer->isSelf()
&& !row->searchInChat();
const auto showRepliesMessages = history->peer->isRepliesChat()
&& !row->searchInChat();
const auto flags = (active ? Flag::Active : Flag(0))
| (selected ? Flag::Selected : Flag(0))
| Flag::SearchResult
| (showSavedMessages ? Flag::SavedMessages : Flag(0))
| (showRepliesMessages ? Flag::RepliesMessages : Flag(0));
paintRow(
p,
row,
history,
history,
FilterId(),
from,
hiddenSenderInfo,
item,
cloudDraft,
ItemDateTime(item),
fullWidth,
flags,
ms,
paintItemCallback,
paintCounterCallback);
if (::Kotato::JsonSettings::GetInt("chat_list_lines") == 1) {
paintOneLineRow(
p,
row,
history,
history,
FilterId(),
from,
hiddenSenderInfo,
item,
cloudDraft,
ItemDateTime(item),
fullWidth,
flags,
ms,
paintItemCallback,
paintCounterCallback);
} else {
paintRow(
p,
row,
history,
history,
FilterId(),
from,
hiddenSenderInfo,
item,
cloudDraft,
ItemDateTime(item),
fullWidth,
flags,
ms,
paintItemCallback,
paintCounterCallback);
}
}
QRect RowPainter::sendActionAnimationRect(
@ -1054,7 +1301,9 @@ QRect RowPainter::sendActionAnimationRect(
int fullWidth,
bool textUpdated) {
const auto nameleft = st::dialogsPadding.x()
+ st::dialogsPhotoSize
+ (::Kotato::JsonSettings::GetInt("chat_list_lines") == 1
? st::dialogsUnreadHeight
: st::dialogsPhotoSize)
+ st::dialogsPhotoPadding;
const auto namewidth = fullWidth - nameleft - st::dialogsPadding.x();
const auto texttop = st::dialogsPadding.y()

View file

@ -312,6 +312,10 @@ const std::map<QString, Definition, std::greater<QString>> DefinitionMap {
{ "scales", {
.type = SettingType::QJsonArraySetting,
.limitHandler = ScalesLimit(), }},
{ "chat_list_lines", {
.type = SettingType::IntSetting,
.defaultValue = 2,
.limitHandler = IntLimit(1, 2, 2), }},
};
using OldOptionKey = QString;

View file

@ -105,6 +105,20 @@ void SetupKotatoChats(
AddSkip(container);
AddSubsectionTitle(container, rktr("ktg_settings_chats"));
AddButton(
container,
rktr("ktg_settings_chat_list_compact"),
st::settingsButton
)->toggleOn(
rpl::single(::Kotato::JsonSettings::GetInt("chat_list_lines") == 1)
)->toggledValue(
) | rpl::filter([](bool enabled) {
return (enabled != (::Kotato::JsonSettings::GetInt("chat_list_lines") == 1));
}) | rpl::start_with_next([](bool enabled) {
::Kotato::JsonSettings::Set("chat_list_lines", enabled ? 1 : 2);
::Kotato::JsonSettings::Write();
}, container->lifetime());
AddButton(
container,
rktr("ktg_settings_always_show_scheduled"),

View file

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "window/window_peer_menu.h"
#include "kotato/kotato_settings.h"
#include "api/api_chat_participants.h"
#include "lang/lang_keys.h"
#include "ui/boxes/confirm_box.h"
@ -809,14 +810,16 @@ void Filler::fillArchiveActions() {
return;
}
const auto controller = _controller;
const auto hidden = controller->session().settings().archiveCollapsed();
const auto text = hidden
? tr::lng_context_archive_expand(tr::now)
: tr::lng_context_archive_collapse(tr::now);
_addAction(text, [=] {
controller->session().settings().setArchiveCollapsed(!hidden);
controller->session().saveSettingsDelayed();
}, hidden ? &st::menuIconExpand : &st::menuIconCollapse);
if (::Kotato::JsonSettings::GetInt("chat_list_lines") != 1) {
const auto hidden = controller->session().settings().archiveCollapsed();
const auto text = hidden
? tr::lng_context_archive_expand(tr::now)
: tr::lng_context_archive_collapse(tr::now);
_addAction(text, [=] {
controller->session().settings().setArchiveCollapsed(!hidden);
controller->session().saveSettingsDelayed();
}, hidden ? &st::menuIconExpand : &st::menuIconCollapse);
}
_addAction(tr::lng_context_archive_to_menu(tr::now), [=] {
Ui::Toast::Show(Ui::Toast::Config{

View file

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "window/window_session_controller.h"
#include "kotato/kotato_settings.h"
#include "boxes/add_contact_box.h"
#include "boxes/peers/edit_peer_info_box.h"
#include "boxes/peer_list_controllers.h"
@ -887,7 +888,7 @@ void SessionController::floatPlayerAreaUpdated() {
}
int SessionController::dialogsSmallColumnWidth() const {
return st::dialogsPadding.x() + st::dialogsPhotoSize + st::dialogsPadding.x();
return st::dialogsPadding.x() + (::Kotato::JsonSettings::GetInt("chat_list_lines") == 1 ? st::dialogsUnreadHeight : st::dialogsPhotoSize) + st::dialogsPadding.x();
}
int SessionController::minimalThreeColumnWidth() const {