mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Add stories-above-chats-list tooltip.
This commit is contained in:
parent
65a344be76
commit
fce8bc6201
12 changed files with 256 additions and 32 deletions
|
@ -3841,6 +3841,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_stories_about_close_friends_my" = "Only your list of **Close Friends** can view this story.";
|
"lng_stories_about_close_friends_my" = "Only your list of **Close Friends** can view this story.";
|
||||||
"lng_stories_about_contacts_my" = "Only your contacts can view this story.";
|
"lng_stories_about_contacts_my" = "Only your contacts can view this story.";
|
||||||
"lng_stories_about_selected_contacts_my" = "Only some contacts you selected can view this story.";
|
"lng_stories_about_selected_contacts_my" = "Only some contacts you selected can view this story.";
|
||||||
|
"lng_stories_click_to_view_mine" = "Click here to view your story.";
|
||||||
"lng_stories_click_to_view" = "Click here to view updates from {users}.";
|
"lng_stories_click_to_view" = "Click here to view updates from {users}.";
|
||||||
"lng_stories_click_to_view_and_one" = "{accumulated}, {user}";
|
"lng_stories_click_to_view_and_one" = "{accumulated}, {user}";
|
||||||
"lng_stories_click_to_view_and_last" = "{accumulated} and {user}";
|
"lng_stories_click_to_view_and_last" = "{accumulated} and {user}";
|
||||||
|
|
|
@ -1338,13 +1338,7 @@ groupCallNiceTooltip: ImportantTooltip(defaultImportantTooltip) {
|
||||||
radius: 4px;
|
radius: 4px;
|
||||||
arrow: 4px;
|
arrow: 4px;
|
||||||
}
|
}
|
||||||
groupCallNiceTooltipLabel: FlatLabel(defaultImportantTooltipLabel) {
|
groupCallNiceTooltipLabel: defaultImportantTooltipLabel;
|
||||||
style: TextStyle(defaultTextStyle) {
|
|
||||||
font: font(11px);
|
|
||||||
linkFont: font(11px);
|
|
||||||
linkFontOver: font(11px underline);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
groupCallStickedTooltip: ImportantTooltip(groupCallNiceTooltip) {
|
groupCallStickedTooltip: ImportantTooltip(groupCallNiceTooltip) {
|
||||||
padding: margins(10px, 1px, 6px, 3px);
|
padding: margins(10px, 1px, 6px, 3px);
|
||||||
}
|
}
|
||||||
|
|
|
@ -200,7 +200,8 @@ QByteArray Settings::serialize() const {
|
||||||
+ sizeof(qint32) * 3
|
+ sizeof(qint32) * 3
|
||||||
+ Serialize::bytearraySize(mediaViewPosition)
|
+ Serialize::bytearraySize(mediaViewPosition)
|
||||||
+ sizeof(qint32)
|
+ sizeof(qint32)
|
||||||
+ sizeof(quint64);
|
+ sizeof(quint64)
|
||||||
|
+ sizeof(qint32);
|
||||||
|
|
||||||
auto result = QByteArray();
|
auto result = QByteArray();
|
||||||
result.reserve(size);
|
result.reserve(size);
|
||||||
|
@ -334,7 +335,8 @@ QByteArray Settings::serialize() const {
|
||||||
<< qint32(_windowTitleContent.current().hideTotalUnread ? 1 : 0)
|
<< qint32(_windowTitleContent.current().hideTotalUnread ? 1 : 0)
|
||||||
<< mediaViewPosition
|
<< mediaViewPosition
|
||||||
<< qint32(_ignoreBatterySaving.current() ? 1 : 0)
|
<< qint32(_ignoreBatterySaving.current() ? 1 : 0)
|
||||||
<< quint64(_macRoundIconDigest.value_or(0));
|
<< quint64(_macRoundIconDigest.value_or(0))
|
||||||
|
<< qint32(_storiesClickTooltipHidden.current() ? 1 : 0);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -440,6 +442,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
|
||||||
QByteArray mediaViewPosition;
|
QByteArray mediaViewPosition;
|
||||||
qint32 ignoreBatterySaving = _ignoreBatterySaving.current() ? 1 : 0;
|
qint32 ignoreBatterySaving = _ignoreBatterySaving.current() ? 1 : 0;
|
||||||
quint64 macRoundIconDigest = _macRoundIconDigest.value_or(0);
|
quint64 macRoundIconDigest = _macRoundIconDigest.value_or(0);
|
||||||
|
qint32 storiesClickTooltipHidden = _storiesClickTooltipHidden.current() ? 1 : 0;
|
||||||
|
|
||||||
stream >> themesAccentColors;
|
stream >> themesAccentColors;
|
||||||
if (!stream.atEnd()) {
|
if (!stream.atEnd()) {
|
||||||
|
@ -674,6 +677,9 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
|
||||||
if (!stream.atEnd()) {
|
if (!stream.atEnd()) {
|
||||||
stream >> macRoundIconDigest;
|
stream >> macRoundIconDigest;
|
||||||
}
|
}
|
||||||
|
if (!stream.atEnd()) {
|
||||||
|
stream >> storiesClickTooltipHidden;
|
||||||
|
}
|
||||||
if (stream.status() != QDataStream::Ok) {
|
if (stream.status() != QDataStream::Ok) {
|
||||||
LOG(("App Error: "
|
LOG(("App Error: "
|
||||||
"Bad data for Core::Settings::constructFromSerialized()"));
|
"Bad data for Core::Settings::constructFromSerialized()"));
|
||||||
|
@ -865,6 +871,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
|
||||||
}
|
}
|
||||||
_ignoreBatterySaving = (ignoreBatterySaving == 1);
|
_ignoreBatterySaving = (ignoreBatterySaving == 1);
|
||||||
_macRoundIconDigest = macRoundIconDigest ? macRoundIconDigest : std::optional<uint64>();
|
_macRoundIconDigest = macRoundIconDigest ? macRoundIconDigest : std::optional<uint64>();
|
||||||
|
_storiesClickTooltipHidden = (storiesClickTooltipHidden == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Settings::getSoundPath(const QString &key) const {
|
QString Settings::getSoundPath(const QString &key) const {
|
||||||
|
@ -1155,6 +1162,7 @@ void Settings::resetOnLastLogout() {
|
||||||
_tabbedReplacedWithInfo = false; // per-window
|
_tabbedReplacedWithInfo = false; // per-window
|
||||||
_systemDarkModeEnabled = false;
|
_systemDarkModeEnabled = false;
|
||||||
_hiddenGroupCallTooltips = 0;
|
_hiddenGroupCallTooltips = 0;
|
||||||
|
_storiesClickTooltipHidden = 0;
|
||||||
|
|
||||||
_recentEmojiPreload.clear();
|
_recentEmojiPreload.clear();
|
||||||
_recentEmoji.clear();
|
_recentEmoji.clear();
|
||||||
|
|
|
@ -802,6 +802,12 @@ public:
|
||||||
[[nodiscard]] std::optional<uint64> macRoundIconDigest() const {
|
[[nodiscard]] std::optional<uint64> macRoundIconDigest() const {
|
||||||
return _macRoundIconDigest;
|
return _macRoundIconDigest;
|
||||||
}
|
}
|
||||||
|
[[nodiscard]] rpl::producer<bool> storiesClickTooltipHiddenValue() const {
|
||||||
|
return _storiesClickTooltipHidden.value();
|
||||||
|
}
|
||||||
|
void setStoriesClickTooltipHidden(bool value) {
|
||||||
|
_storiesClickTooltipHidden = value;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] static bool ThirdColumnByDefault();
|
[[nodiscard]] static bool ThirdColumnByDefault();
|
||||||
[[nodiscard]] static float64 DefaultDialogsWidthRatio();
|
[[nodiscard]] static float64 DefaultDialogsWidthRatio();
|
||||||
|
@ -923,6 +929,7 @@ private:
|
||||||
WindowPosition _mediaViewPosition = { .maximized = 2 };
|
WindowPosition _mediaViewPosition = { .maximized = 2 };
|
||||||
rpl::variable<bool> _ignoreBatterySaving = false;
|
rpl::variable<bool> _ignoreBatterySaving = false;
|
||||||
std::optional<uint64> _macRoundIconDigest;
|
std::optional<uint64> _macRoundIconDigest;
|
||||||
|
rpl::variable<bool> _storiesClickTooltipHidden = false;
|
||||||
|
|
||||||
bool _tabbedReplacedWithInfo = false; // per-window
|
bool _tabbedReplacedWithInfo = false; // per-window
|
||||||
rpl::event_stream<bool> _tabbedReplacedWithInfoValue; // per-window
|
rpl::event_stream<bool> _tabbedReplacedWithInfoValue; // per-window
|
||||||
|
|
|
@ -562,3 +562,6 @@ dialogsStoriesListInfo: DialogsStoriesList(dialogsStoriesList) {
|
||||||
dialogsStoriesListMine: DialogsStoriesList(dialogsStoriesListInfo) {
|
dialogsStoriesListMine: DialogsStoriesList(dialogsStoriesListInfo) {
|
||||||
readOpacity: 1.;
|
readOpacity: 1.;
|
||||||
}
|
}
|
||||||
|
dialogsStoriesTooltip: defaultImportantTooltip;
|
||||||
|
dialogsStoriesTooltipLabel: defaultImportantTooltipLabel;
|
||||||
|
dialogsStoriesTooltipMaxWidth: 200px;
|
||||||
|
|
|
@ -798,6 +798,15 @@ void Widget::setupStories() {
|
||||||
_scroll->viewportEvent(e);
|
_scroll->viewportEvent(e);
|
||||||
}, _stories->lifetime());
|
}, _stories->lifetime());
|
||||||
|
|
||||||
|
const auto hideTooltip = [=] {
|
||||||
|
Core::App().settings().setStoriesClickTooltipHidden(true);
|
||||||
|
Core::App().saveSettingsDelayed();
|
||||||
|
};
|
||||||
|
_stories->setShowTooltip(
|
||||||
|
Core::App().settings().storiesClickTooltipHiddenValue(
|
||||||
|
) | rpl::map(!rpl::mappers::_1),
|
||||||
|
hideTooltip);
|
||||||
|
|
||||||
_storiesContents.fire(Stories::ContentForSession(
|
_storiesContents.fire(Stories::ContentForSession(
|
||||||
&controller()->session(),
|
&controller()->session(),
|
||||||
Data::StorySourcesList::NotHidden));
|
Data::StorySourcesList::NotHidden));
|
||||||
|
|
|
@ -7,14 +7,20 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#include "dialogs/ui/dialogs_stories_list.h"
|
#include "dialogs/ui/dialogs_stories_list.h"
|
||||||
|
|
||||||
|
#include "base/event_filter.h"
|
||||||
|
#include "base/qt_signal_producer.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "ui/effects/outline_segments.h"
|
#include "ui/effects/outline_segments.h"
|
||||||
|
#include "ui/text/text_utilities.h"
|
||||||
#include "ui/widgets/menu/menu_add_action_callback_factory.h"
|
#include "ui/widgets/menu/menu_add_action_callback_factory.h"
|
||||||
|
#include "ui/widgets/labels.h"
|
||||||
#include "ui/widgets/popup_menu.h"
|
#include "ui/widgets/popup_menu.h"
|
||||||
|
#include "ui/widgets/tooltip.h"
|
||||||
#include "ui/painter.h"
|
#include "ui/painter.h"
|
||||||
#include "styles/style_dialogs.h"
|
#include "styles/style_dialogs.h"
|
||||||
|
|
||||||
#include <QtWidgets/QApplication>
|
#include <QtWidgets/QApplication>
|
||||||
|
#include <QtGui/QWindow>
|
||||||
|
|
||||||
#include "base/debug_log.h"
|
#include "base/debug_log.h"
|
||||||
|
|
||||||
|
@ -27,6 +33,7 @@ constexpr auto kExpandAfterRatio = 0.72;
|
||||||
constexpr auto kCollapseAfterRatio = 0.68;
|
constexpr auto kCollapseAfterRatio = 0.68;
|
||||||
constexpr auto kFrictionRatio = 0.15;
|
constexpr auto kFrictionRatio = 0.15;
|
||||||
constexpr auto kExpandCatchUpDuration = crl::time(200);
|
constexpr auto kExpandCatchUpDuration = crl::time(200);
|
||||||
|
constexpr auto kMaxTooltipNames = 3;
|
||||||
|
|
||||||
[[nodiscard]] int AvailableNameWidth(const style::DialogsStoriesList &st) {
|
[[nodiscard]] int AvailableNameWidth(const style::DialogsStoriesList &st) {
|
||||||
const auto &full = st.full;
|
const auto &full = st.full;
|
||||||
|
@ -112,6 +119,7 @@ void List::showContent(Content &&content) {
|
||||||
_data.items.emplace_back(Item{ .element = element });
|
_data.items.emplace_back(Item{ .element = element });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_lastCollapsedGeometry = {};
|
||||||
if (int(_data.items.size()) != wasCount) {
|
if (int(_data.items.size()) != wasCount) {
|
||||||
updateGeometry();
|
updateGeometry();
|
||||||
}
|
}
|
||||||
|
@ -120,6 +128,8 @@ void List::showContent(Content &&content) {
|
||||||
if (!wasCount) {
|
if (!wasCount) {
|
||||||
_empty = false;
|
_empty = false;
|
||||||
}
|
}
|
||||||
|
_tooltipText = computeTooltipText();
|
||||||
|
updateTooltipGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
void List::updateScrollMax() {
|
void List::updateScrollMax() {
|
||||||
|
@ -162,10 +172,16 @@ void List::requestExpanded(bool expanded) {
|
||||||
const auto from = _expanded ? 0. : 1.;
|
const auto from = _expanded ? 0. : 1.;
|
||||||
const auto till = _expanded ? 2. : 0.;
|
const auto till = _expanded ? 2. : 0.;
|
||||||
const auto duration = (_expanded ? 2 : 1) * st::slideWrapDuration;
|
const auto duration = (_expanded ? 2 : 1) * st::slideWrapDuration;
|
||||||
|
if (!isHidden() && _expanded) {
|
||||||
|
toggleTooltip(false);
|
||||||
|
}
|
||||||
_expandedAnimation.start([=] {
|
_expandedAnimation.start([=] {
|
||||||
checkForFullState();
|
checkForFullState();
|
||||||
update();
|
update();
|
||||||
_collapsedGeometryChanged.fire({});
|
_collapsedGeometryChanged.fire({});
|
||||||
|
if (!isHidden() && !_expandedAnimation.animating()) {
|
||||||
|
toggleTooltip(false);
|
||||||
|
}
|
||||||
}, from, till, duration, anim::sineInOut);
|
}, from, till, duration, anim::sineInOut);
|
||||||
}
|
}
|
||||||
_toggleExpandedRequests.fire_copy(_expanded);
|
_toggleExpandedRequests.fire_copy(_expanded);
|
||||||
|
@ -179,6 +195,12 @@ void List::resizeEvent(QResizeEvent *e) {
|
||||||
updateScrollMax();
|
updateScrollMax();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void List::updateExpanding() {
|
||||||
|
updateExpanding(
|
||||||
|
_lastExpandedHeight * _expandCatchUpAnimation.value(1.),
|
||||||
|
_st.full.height);
|
||||||
|
}
|
||||||
|
|
||||||
void List::updateExpanding(int expandingHeight, int expandedHeight) {
|
void List::updateExpanding(int expandingHeight, int expandedHeight) {
|
||||||
Expects(!expandingHeight || expandedHeight > 0);
|
Expects(!expandingHeight || expandedHeight > 0);
|
||||||
|
|
||||||
|
@ -196,12 +218,10 @@ void List::updateExpanding(int expandingHeight, int expandedHeight) {
|
||||||
if (change) {
|
if (change) {
|
||||||
requestExpanded(!_expanded);
|
requestExpanded(!_expanded);
|
||||||
}
|
}
|
||||||
|
updateTooltipGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
List::Layout List::computeLayout() {
|
List::Layout List::computeLayout() {
|
||||||
updateExpanding(
|
|
||||||
_lastExpandedHeight * _expandCatchUpAnimation.value(1.),
|
|
||||||
_st.full.height);
|
|
||||||
return computeLayout(_expandedAnimation.value(_expanded ? 2. : 0.));
|
return computeLayout(_expandedAnimation.value(_expanded ? 2. : 0.));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -678,6 +698,9 @@ void List::mousePressEvent(QMouseEvent *e) {
|
||||||
return;
|
return;
|
||||||
} else if (_state == State::Small) {
|
} else if (_state == State::Small) {
|
||||||
requestExpanded(true);
|
requestExpanded(true);
|
||||||
|
if (const auto onstack = _tooltipHide) {
|
||||||
|
onstack();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
} else if (_state != State::Full) {
|
} else if (_state != State::Full) {
|
||||||
return;
|
return;
|
||||||
|
@ -757,6 +780,7 @@ void List::setExpandedHeight(int height, bool momentum) {
|
||||||
} else if (!momentum && _expandIgnored && height > 0) {
|
} else if (!momentum && _expandIgnored && height > 0) {
|
||||||
_expandIgnored = false;
|
_expandIgnored = false;
|
||||||
_expandCatchUpAnimation.start([=] {
|
_expandCatchUpAnimation.start([=] {
|
||||||
|
updateExpanding();
|
||||||
update();
|
update();
|
||||||
checkForFullState();
|
checkForFullState();
|
||||||
}, 0., 1., kExpandCatchUpDuration);
|
}, 0., 1., kExpandCatchUpDuration);
|
||||||
|
@ -764,6 +788,7 @@ void List::setExpandedHeight(int height, bool momentum) {
|
||||||
_expandCatchUpAnimation.stop();
|
_expandCatchUpAnimation.stop();
|
||||||
}
|
}
|
||||||
_lastExpandedHeight = height;
|
_lastExpandedHeight = height;
|
||||||
|
updateExpanding();
|
||||||
if (!checkForFullState()) {
|
if (!checkForFullState()) {
|
||||||
setState(!height ? State::Small : State::Changing);
|
setState(!height ? State::Small : State::Changing);
|
||||||
}
|
}
|
||||||
|
@ -784,17 +809,177 @@ void List::setLayoutConstraints(
|
||||||
QPoint positionSmall,
|
QPoint positionSmall,
|
||||||
style::align alignSmall,
|
style::align alignSmall,
|
||||||
QRect geometryFull) {
|
QRect geometryFull) {
|
||||||
|
if (_positionSmall == positionSmall
|
||||||
|
&& _alignSmall == alignSmall
|
||||||
|
&& _geometryFull == geometryFull) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
_positionSmall = positionSmall;
|
_positionSmall = positionSmall;
|
||||||
_alignSmall = alignSmall;
|
_alignSmall = alignSmall;
|
||||||
_geometryFull = geometryFull;
|
_geometryFull = geometryFull;
|
||||||
|
_lastCollapsedGeometry = {};
|
||||||
updateGeometry();
|
updateGeometry();
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextWithEntities List::computeTooltipText() const {
|
||||||
|
const auto &list = _data.items;
|
||||||
|
if (list.empty()) {
|
||||||
|
return {};
|
||||||
|
} else if (list.size() == 1 && list.front().element.skipSmall) {
|
||||||
|
return { tr::lng_stories_click_to_view_mine(tr::now) };
|
||||||
|
}
|
||||||
|
auto names = QStringList();
|
||||||
|
for (const auto &item : list) {
|
||||||
|
if (item.element.skipSmall) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
names.append(item.element.name);
|
||||||
|
if (names.size() >= kMaxTooltipNames) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto sequence = Ui::Text::Bold(names.front());
|
||||||
|
if (names.size() > 1) {
|
||||||
|
for (auto i = 1; i + 1 != names.size(); ++i) {
|
||||||
|
sequence = tr::lng_stories_click_to_view_and_one(
|
||||||
|
tr::now,
|
||||||
|
lt_accumulated,
|
||||||
|
sequence,
|
||||||
|
lt_user,
|
||||||
|
Ui::Text::Bold(names[i]),
|
||||||
|
Ui::Text::WithEntities);
|
||||||
|
}
|
||||||
|
sequence = tr::lng_stories_click_to_view_and_last(
|
||||||
|
tr::now,
|
||||||
|
lt_accumulated,
|
||||||
|
sequence,
|
||||||
|
lt_user,
|
||||||
|
Ui::Text::Bold(names.back()),
|
||||||
|
Ui::Text::WithEntities);
|
||||||
|
}
|
||||||
|
return tr::lng_stories_click_to_view(
|
||||||
|
tr::now,
|
||||||
|
lt_users,
|
||||||
|
sequence,
|
||||||
|
Ui::Text::WithEntities);
|
||||||
|
}
|
||||||
|
|
||||||
|
void List::setShowTooltip(rpl::producer<bool> shown, Fn<void()> hide) {
|
||||||
|
_tooltip = nullptr;
|
||||||
|
_tooltipHide = std::move(hide);
|
||||||
|
_tooltipNotHidden = std::move(shown);
|
||||||
|
_tooltipText = computeTooltipText();
|
||||||
|
const auto window = this->window();
|
||||||
|
const auto notEmpty = [](const TextWithEntities &text) {
|
||||||
|
return !text.empty();
|
||||||
|
};
|
||||||
|
_tooltip = std::make_unique<Ui::ImportantTooltip>(
|
||||||
|
window,
|
||||||
|
Ui::MakeNiceTooltipLabel(
|
||||||
|
window,
|
||||||
|
_tooltipText.value() | rpl::filter(notEmpty),
|
||||||
|
st::dialogsStoriesTooltipMaxWidth,
|
||||||
|
st::dialogsStoriesTooltipLabel),
|
||||||
|
st::dialogsStoriesTooltip);
|
||||||
|
const auto tooltip = _tooltip.get();
|
||||||
|
const auto weak = QPointer<QWidget>(tooltip);
|
||||||
|
tooltip->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
|
tooltip->toggleFast(false);
|
||||||
|
updateTooltipGeometry();
|
||||||
|
|
||||||
|
const auto handle = window->windowHandle();
|
||||||
|
auto windowActive = rpl::single(
|
||||||
|
handle->isActive()
|
||||||
|
) | rpl::then(base::qt_signal_producer(
|
||||||
|
handle,
|
||||||
|
&QWindow::activeChanged
|
||||||
|
) | rpl::map([=] {
|
||||||
|
return handle->isActive();
|
||||||
|
})) | rpl::distinct_until_changed();
|
||||||
|
|
||||||
|
for (auto parent = parentWidget()
|
||||||
|
; parent != window
|
||||||
|
; parent = parent->parentWidget()) {
|
||||||
|
using namespace base;
|
||||||
|
install_event_filter(parent, tooltip, [=](not_null<QEvent*> e) {
|
||||||
|
if (e->type() == QEvent::Move) {
|
||||||
|
updateTooltipGeometry();
|
||||||
|
}
|
||||||
|
return EventFilterResult::Continue;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::combine(
|
||||||
|
_tooltipNotHidden.value(),
|
||||||
|
_tooltipText.value() | rpl::map(
|
||||||
|
notEmpty
|
||||||
|
) | rpl::distinct_until_changed(),
|
||||||
|
std::move(windowActive)
|
||||||
|
) | rpl::start_with_next([=](bool, bool, bool active) {
|
||||||
|
_tooltipWindowActive = active;
|
||||||
|
if (!isHidden()) {
|
||||||
|
toggleTooltip(false);
|
||||||
|
}
|
||||||
|
}, tooltip->lifetime());
|
||||||
|
|
||||||
|
shownValue(
|
||||||
|
) | rpl::skip(1) | rpl::start_with_next([=](bool shown) {
|
||||||
|
toggleTooltip(true);
|
||||||
|
}, tooltip->lifetime());
|
||||||
|
}
|
||||||
|
|
||||||
|
void List::toggleTooltip(bool fast) {
|
||||||
|
const auto shown = !_expanded
|
||||||
|
&& !_expandedAnimation.animating()
|
||||||
|
&& !isHidden()
|
||||||
|
&& _tooltipNotHidden.current()
|
||||||
|
&& !_tooltipText.current().empty()
|
||||||
|
&& window()->windowHandle()->isActive();
|
||||||
|
if (shown) {
|
||||||
|
updateTooltipGeometry();
|
||||||
|
}
|
||||||
|
if (fast) {
|
||||||
|
_tooltip->toggleFast(shown);
|
||||||
|
} else {
|
||||||
|
_tooltip->toggleAnimated(shown);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void List::updateTooltipGeometry() {
|
||||||
|
if (!_tooltip || _expanded || _expandedAnimation.animating()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto collapsed = collapsedGeometryCurrent();
|
||||||
|
if (collapsed.geometry.isEmpty()) {
|
||||||
|
int a = 0;
|
||||||
|
}
|
||||||
|
const auto geometry = Ui::MapFrom(
|
||||||
|
window(),
|
||||||
|
parentWidget(),
|
||||||
|
QRect(
|
||||||
|
collapsed.geometry.x(),
|
||||||
|
collapsed.geometry.y(),
|
||||||
|
int(std::ceil(collapsed.singleWidth)),
|
||||||
|
collapsed.geometry.height()));
|
||||||
|
const auto weak = QPointer<QWidget>(_tooltip.get());
|
||||||
|
const auto countPosition = [=](QSize size) {
|
||||||
|
return QPoint(
|
||||||
|
geometry.x() + (geometry.width() - size.width()) / 2,
|
||||||
|
geometry.y() + geometry.height());
|
||||||
|
};
|
||||||
|
_tooltip->pointAt(geometry, RectPart::Bottom, countPosition);
|
||||||
|
}
|
||||||
|
|
||||||
List::CollapsedGeometry List::collapsedGeometryCurrent() const {
|
List::CollapsedGeometry List::collapsedGeometryCurrent() const {
|
||||||
const auto expanded = _expandedAnimation.value(_expanded ? 2. : 0.);
|
const auto expanded = _expandedAnimation.value(_expanded ? 2. : 0.);
|
||||||
if (expanded >= 1.) {
|
if (expanded >= 1.) {
|
||||||
return { QRect(), 1. };
|
const auto single = 2 * _st.full.photoLeft + _st.full.photo;
|
||||||
|
return { QRect(), 1., float64(single) };
|
||||||
|
} else if (_lastCollapsedRatio == _lastRatio
|
||||||
|
&& _lastCollapsedGeometry.expanded == expanded
|
||||||
|
&& !_lastCollapsedGeometry.geometry.isEmpty()) {
|
||||||
|
return _lastCollapsedGeometry;
|
||||||
}
|
}
|
||||||
const auto layout = computeLayout(0.);
|
const auto layout = computeLayout(0.);
|
||||||
const auto small = countSmallGeometry();
|
const auto small = countSmallGeometry();
|
||||||
|
@ -803,10 +988,21 @@ List::CollapsedGeometry List::collapsedGeometryCurrent() const {
|
||||||
const auto left = int(base::SafeRound(
|
const auto left = int(base::SafeRound(
|
||||||
shift + layout.left + layout.single * index));
|
shift + layout.left + layout.single * index));
|
||||||
const auto width = small.x() + small.width() - left;
|
const auto width = small.x() + small.width() - left;
|
||||||
return {
|
const auto photoTopSmall = _st.small.photoTop;
|
||||||
QRect(left, small.y(), width, small.height()),
|
const auto photoTop = photoTopSmall
|
||||||
|
+ (_st.full.photoTop - photoTopSmall) * layout.expandedRatio;
|
||||||
|
const auto ySmall = photoTopSmall
|
||||||
|
+ ((photoTop - photoTopSmall) * kSmallThumbsShown / 0.5);
|
||||||
|
const auto photo = _st.small.photo
|
||||||
|
+ (_st.full.photo - _st.small.photo) * layout.ratio;
|
||||||
|
const auto top = y() + layout.geometryShift.y();
|
||||||
|
_lastCollapsedRatio = _lastRatio;
|
||||||
|
_lastCollapsedGeometry = {
|
||||||
|
QRect(left, top, width, ySmall + photo + _st.full.photoTop),
|
||||||
expanded,
|
expanded,
|
||||||
|
layout.photoLeft * 2 + photo,
|
||||||
};
|
};
|
||||||
|
return _lastCollapsedGeometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<> List::collapsedGeometryChanged() const {
|
rpl::producer<> List::collapsedGeometryChanged() const {
|
||||||
|
@ -822,6 +1018,7 @@ void List::updateGeometry() {
|
||||||
} break;
|
} break;
|
||||||
case State::Full: setGeometry(_geometryFull);
|
case State::Full: setGeometry(_geometryFull);
|
||||||
}
|
}
|
||||||
|
updateTooltipGeometry();
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ struct DialogsStoriesList;
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class PopupMenu;
|
class PopupMenu;
|
||||||
struct OutlineSegment;
|
struct OutlineSegment;
|
||||||
|
class ImportantTooltip;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
namespace Dialogs::Stories {
|
namespace Dialogs::Stories {
|
||||||
|
@ -72,9 +73,11 @@ public:
|
||||||
QPoint positionSmall,
|
QPoint positionSmall,
|
||||||
style::align alignSmall,
|
style::align alignSmall,
|
||||||
QRect geometryFull = QRect());
|
QRect geometryFull = QRect());
|
||||||
|
void setShowTooltip(rpl::producer<bool> shown, Fn<void()> hide);
|
||||||
struct CollapsedGeometry {
|
struct CollapsedGeometry {
|
||||||
QRect geometry;
|
QRect geometry;
|
||||||
float64 expanded = 0.;
|
float64 expanded = 0.;
|
||||||
|
float64 singleWidth = 0.;
|
||||||
};
|
};
|
||||||
[[nodiscard]] CollapsedGeometry collapsedGeometryCurrent() const;
|
[[nodiscard]] CollapsedGeometry collapsedGeometryCurrent() const;
|
||||||
[[nodiscard]] rpl::producer<> collapsedGeometryChanged() const;
|
[[nodiscard]] rpl::producer<> collapsedGeometryChanged() const;
|
||||||
|
@ -142,10 +145,15 @@ private:
|
||||||
void checkLoadMore();
|
void checkLoadMore();
|
||||||
void requestExpanded(bool expanded);
|
void requestExpanded(bool expanded);
|
||||||
|
|
||||||
|
void updateTooltipGeometry();
|
||||||
|
[[nodiscard]] TextWithEntities computeTooltipText() const;
|
||||||
|
void toggleTooltip(bool fast);
|
||||||
|
|
||||||
bool checkForFullState();
|
bool checkForFullState();
|
||||||
void setState(State state);
|
void setState(State state);
|
||||||
void updateGeometry();
|
void updateGeometry();
|
||||||
[[nodiscard]] QRect countSmallGeometry() const;
|
[[nodiscard]] QRect countSmallGeometry() const;
|
||||||
|
void updateExpanding();
|
||||||
void updateExpanding(int expandingHeight, int expandedHeight);
|
void updateExpanding(int expandingHeight, int expandedHeight);
|
||||||
void validateSegments(
|
void validateSegments(
|
||||||
not_null<Item*> item,
|
not_null<Item*> item,
|
||||||
|
@ -189,11 +197,20 @@ private:
|
||||||
bool _expandIgnored : 1 = false;
|
bool _expandIgnored : 1 = false;
|
||||||
bool _expanded : 1 = false;
|
bool _expanded : 1 = false;
|
||||||
|
|
||||||
|
mutable CollapsedGeometry _lastCollapsedGeometry;
|
||||||
|
mutable float64 _lastCollapsedRatio = 0.;
|
||||||
|
|
||||||
int _selected = -1;
|
int _selected = -1;
|
||||||
int _pressed = -1;
|
int _pressed = -1;
|
||||||
|
|
||||||
rpl::event_stream<not_null<QWheelEvent*>> _verticalScrollEvents;
|
rpl::event_stream<not_null<QWheelEvent*>> _verticalScrollEvents;
|
||||||
|
|
||||||
|
rpl::variable<TextWithEntities> _tooltipText;
|
||||||
|
rpl::variable<bool> _tooltipNotHidden;
|
||||||
|
Fn<void()> _tooltipHide;
|
||||||
|
std::unique_ptr<Ui::ImportantTooltip> _tooltip;
|
||||||
|
bool _tooltipWindowActive = false;
|
||||||
|
|
||||||
base::unique_qptr<Ui::PopupMenu> _menu;
|
base::unique_qptr<Ui::PopupMenu> _menu;
|
||||||
base::has_weak_ptr _menuGuard;
|
base::has_weak_ptr _menuGuard;
|
||||||
|
|
||||||
|
|
|
@ -315,7 +315,7 @@ void Header::show(HeaderData data) {
|
||||||
raw,
|
raw,
|
||||||
rpl::single(data.user->isSelf()
|
rpl::single(data.user->isSelf()
|
||||||
? tr::lng_stories_my_name(tr::now)
|
? tr::lng_stories_my_name(tr::now)
|
||||||
: data.user->shortName()),
|
: data.user->name()),
|
||||||
st::storiesHeaderName);
|
st::storiesHeaderName);
|
||||||
_name->setAttribute(Qt::WA_TransparentForMouseEvents);
|
_name->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
_name->setOpacity(kNameOpacity);
|
_name->setOpacity(kNameOpacity);
|
||||||
|
|
|
@ -93,7 +93,7 @@ private:
|
||||||
std::unique_ptr<Ui::RpWidget> _privacy;
|
std::unique_ptr<Ui::RpWidget> _privacy;
|
||||||
QRect _privacyBadgeGeometry;
|
QRect _privacyBadgeGeometry;
|
||||||
std::optional<HeaderData> _data;
|
std::optional<HeaderData> _data;
|
||||||
std::unique_ptr<Ui::ImportantTooltip> _tooltip = { nullptr };
|
std::unique_ptr<Ui::ImportantTooltip> _tooltip;
|
||||||
rpl::variable<bool> _tooltipShown = false;
|
rpl::variable<bool> _tooltipShown = false;
|
||||||
QRect _contentGeometry;
|
QRect _contentGeometry;
|
||||||
Tooltip _tooltipType = {};
|
Tooltip _tooltipType = {};
|
||||||
|
|
|
@ -891,18 +891,6 @@ storiesVolumeSlider: MediaSlider {
|
||||||
seekSize: size(12px, 12px);
|
seekSize: size(12px, 12px);
|
||||||
duration: mediaviewOverDuration;
|
duration: mediaviewOverDuration;
|
||||||
}
|
}
|
||||||
storiesInfoTooltipLabel: FlatLabel(defaultImportantTooltipLabel) {
|
storiesInfoTooltipLabel: defaultImportantTooltipLabel;
|
||||||
style: TextStyle(defaultTextStyle) {
|
storiesInfoTooltip: defaultImportantTooltip;
|
||||||
font: font(11px);
|
|
||||||
linkFont: font(11px);
|
|
||||||
linkFontOver: font(11px underline);
|
|
||||||
}
|
|
||||||
minWidth: 36px;
|
|
||||||
}
|
|
||||||
storiesInfoTooltip: ImportantTooltip(defaultImportantTooltip) {
|
|
||||||
bg: importantTooltipBg;
|
|
||||||
padding: margins(10px, 3px, 10px, 5px);
|
|
||||||
radius: 4px;
|
|
||||||
arrow: 4px;
|
|
||||||
}
|
|
||||||
storiesInfoTooltipMaxWidth: 360px;
|
storiesInfoTooltipMaxWidth: 360px;
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit bd1e8f7c47c3e99493adf9653d684c86a0a51941
|
Subproject commit 8314fc9b3f292dd9921ef2bfa1c30bcfd2ed05ed
|
Loading…
Add table
Reference in a new issue