mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Fix shortcut messages sizing / emoji panel.
This commit is contained in:
parent
aad8e989d8
commit
8545a14763
21 changed files with 253 additions and 82 deletions
|
@ -89,6 +89,9 @@ mtpRequestId EditMessage(
|
||||||
: emptyFlag)
|
: emptyFlag)
|
||||||
| (options.scheduled
|
| (options.scheduled
|
||||||
? MTPmessages_EditMessage::Flag::f_schedule_date
|
? MTPmessages_EditMessage::Flag::f_schedule_date
|
||||||
|
: emptyFlag)
|
||||||
|
| (item->isBusinessShortcut()
|
||||||
|
? MTPmessages_EditMessage::Flag::f_quick_reply_shortcut_id
|
||||||
: emptyFlag);
|
: emptyFlag);
|
||||||
|
|
||||||
const auto id = item->isScheduled()
|
const auto id = item->isScheduled()
|
||||||
|
@ -105,7 +108,7 @@ mtpRequestId EditMessage(
|
||||||
MTPReplyMarkup(),
|
MTPReplyMarkup(),
|
||||||
sentEntities,
|
sentEntities,
|
||||||
MTP_int(options.scheduled),
|
MTP_int(options.scheduled),
|
||||||
MTPint() // quick_reply_shortcut_id
|
MTP_int(item->shortcutId())
|
||||||
)).done([=](
|
)).done([=](
|
||||||
const MTPUpdates &result,
|
const MTPUpdates &result,
|
||||||
[[maybe_unused]] mtpRequestId requestId) {
|
[[maybe_unused]] mtpRequestId requestId) {
|
||||||
|
|
|
@ -895,6 +895,7 @@ void EditCaptionBox::save() {
|
||||||
|
|
||||||
auto options = Api::SendOptions();
|
auto options = Api::SendOptions();
|
||||||
options.scheduled = item->isScheduled() ? item->date() : 0;
|
options.scheduled = item->isScheduled() ? item->date() : 0;
|
||||||
|
options.shortcutId = item->shortcutId();
|
||||||
|
|
||||||
if (!_preparedList.files.empty()) {
|
if (!_preparedList.files.empty()) {
|
||||||
if ((_albumType != Ui::AlbumType::None)
|
if ((_albumType != Ui::AlbumType::None)
|
||||||
|
|
|
@ -23,6 +23,7 @@ struct ComposeFeatures {
|
||||||
bool autocompleteHashtags = true;
|
bool autocompleteHashtags = true;
|
||||||
bool autocompleteMentions = true;
|
bool autocompleteMentions = true;
|
||||||
bool autocompleteCommands = true;
|
bool autocompleteCommands = true;
|
||||||
|
bool commonTabbedPanel = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ChatHelpers
|
} // namespace ChatHelpers
|
||||||
|
|
|
@ -60,7 +60,8 @@ constexpr auto kRequestTimeLimit = 60 * crl::time(1000);
|
||||||
MTP_int(data.vttl_period().value_or_empty()));
|
MTP_int(data.vttl_period().value_or_empty()));
|
||||||
}, [&](const MTPDmessage &data) {
|
}, [&](const MTPDmessage &data) {
|
||||||
return MTP_message(
|
return MTP_message(
|
||||||
MTP_flags(data.vflags().v | MTPDmessage::Flag::f_quick_reply_shortcut_id),
|
MTP_flags(data.vflags().v
|
||||||
|
| MTPDmessage::Flag::f_quick_reply_shortcut_id),
|
||||||
data.vid(),
|
data.vid(),
|
||||||
data.vfrom_id() ? *data.vfrom_id() : MTPPeer(),
|
data.vfrom_id() ? *data.vfrom_id() : MTPPeer(),
|
||||||
MTPint(), // from_boosts_applied
|
MTPint(), // from_boosts_applied
|
||||||
|
|
|
@ -96,6 +96,18 @@ public:
|
||||||
[[nodiscard]] static constexpr DraftKey ScheduledEdit() {
|
[[nodiscard]] static constexpr DraftKey ScheduledEdit() {
|
||||||
return kScheduledDraftIndex + kEditDraftShift;
|
return kScheduledDraftIndex + kEditDraftShift;
|
||||||
}
|
}
|
||||||
|
[[nodiscard]] static constexpr DraftKey Shortcut(
|
||||||
|
BusinessShortcutId shortcutId) {
|
||||||
|
return (shortcutId < 0 || shortcutId >= ServerMaxMsgId)
|
||||||
|
? None()
|
||||||
|
: (kShortcutDraftShift + shortcutId);
|
||||||
|
}
|
||||||
|
[[nodiscard]] static constexpr DraftKey ShortcutEdit(
|
||||||
|
BusinessShortcutId shortcutId) {
|
||||||
|
return (shortcutId < 0 || shortcutId >= ServerMaxMsgId)
|
||||||
|
? None()
|
||||||
|
: (kShortcutDraftShift + kEditDraftShift + shortcutId);
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] static constexpr DraftKey FromSerialized(qint64 value) {
|
[[nodiscard]] static constexpr DraftKey FromSerialized(qint64 value) {
|
||||||
return value;
|
return value;
|
||||||
|
@ -156,6 +168,7 @@ private:
|
||||||
static constexpr auto kScheduledDraftIndex = -3;
|
static constexpr auto kScheduledDraftIndex = -3;
|
||||||
static constexpr auto kEditDraftShift = ServerMaxMsgId.bare;
|
static constexpr auto kEditDraftShift = ServerMaxMsgId.bare;
|
||||||
static constexpr auto kCloudDraftShift = 2 * ServerMaxMsgId.bare;
|
static constexpr auto kCloudDraftShift = 2 * ServerMaxMsgId.bare;
|
||||||
|
static constexpr auto kShortcutDraftShift = 3 * ServerMaxMsgId.bare;
|
||||||
static constexpr auto kEditDraftShiftOld = 0x3FFF'FFFF;
|
static constexpr auto kEditDraftShiftOld = 0x3FFF'FFFF;
|
||||||
|
|
||||||
int64 _value = 0;
|
int64 _value = 0;
|
||||||
|
|
|
@ -108,6 +108,7 @@ struct EntryState {
|
||||||
Replies,
|
Replies,
|
||||||
SavedSublist,
|
SavedSublist,
|
||||||
ContextMenu,
|
ContextMenu,
|
||||||
|
ShortcutMessages,
|
||||||
};
|
};
|
||||||
|
|
||||||
Key key;
|
Key key;
|
||||||
|
|
|
@ -2108,7 +2108,7 @@ bool HistoryItem::allowsEdit(TimeId now) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HistoryItem::canBeEdited() const {
|
bool HistoryItem::canBeEdited() const {
|
||||||
if ((!isRegular() && !isScheduled())
|
if ((!isRegular() && !isScheduled() && !isBusinessShortcut())
|
||||||
|| Has<HistoryMessageVia>()
|
|| Has<HistoryMessageVia>()
|
||||||
|| Has<HistoryMessageForwarded>()) {
|
|| Has<HistoryMessageForwarded>()) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -114,6 +114,9 @@ using ForwardPanel = Controls::ForwardPanel;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
const ChatHelpers::PauseReason kDefaultPanelsLevel
|
||||||
|
= ChatHelpers::PauseReason::TabbedPanel;
|
||||||
|
|
||||||
class FieldHeader final : public Ui::RpWidget {
|
class FieldHeader final : public Ui::RpWidget {
|
||||||
public:
|
public:
|
||||||
FieldHeader(
|
FieldHeader(
|
||||||
|
@ -760,7 +763,10 @@ MessageToEdit FieldHeader::queryToEdit() {
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
.fullId = item->fullId(),
|
.fullId = item->fullId(),
|
||||||
.options = { .scheduled = item->isScheduled() ? item->date() : 0 },
|
.options = {
|
||||||
|
.scheduled = item->isScheduled() ? item->date() : 0,
|
||||||
|
.shortcutId = item->shortcutId(),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -788,21 +794,24 @@ ComposeControls::ComposeControls(
|
||||||
: st::defaultComposeControls)
|
: st::defaultComposeControls)
|
||||||
, _features(descriptor.features)
|
, _features(descriptor.features)
|
||||||
, _parent(parent)
|
, _parent(parent)
|
||||||
|
, _panelsParent(descriptor.panelsParent
|
||||||
|
? descriptor.panelsParent
|
||||||
|
: _parent.get())
|
||||||
, _show(std::move(descriptor.show))
|
, _show(std::move(descriptor.show))
|
||||||
, _session(&_show->session())
|
, _session(&_show->session())
|
||||||
, _regularWindow(descriptor.regularWindow)
|
, _regularWindow(descriptor.regularWindow)
|
||||||
, _ownedSelector(_regularWindow
|
, _ownedSelector((_regularWindow && _features.commonTabbedPanel)
|
||||||
? nullptr
|
? nullptr
|
||||||
: std::make_unique<ChatHelpers::TabbedSelector>(
|
: std::make_unique<ChatHelpers::TabbedSelector>(
|
||||||
_parent,
|
_panelsParent,
|
||||||
ChatHelpers::TabbedSelectorDescriptor{
|
ChatHelpers::TabbedSelectorDescriptor{
|
||||||
.show = _show,
|
.show = _show,
|
||||||
.st = _st.tabbed,
|
.st = _st.tabbed,
|
||||||
.level = Window::GifPauseReason::TabbedPanel,
|
.level = descriptor.panelsLevel,
|
||||||
.mode = ChatHelpers::TabbedSelector::Mode::Full,
|
.mode = ChatHelpers::TabbedSelector::Mode::Full,
|
||||||
.features = _features,
|
.features = _features,
|
||||||
}))
|
}))
|
||||||
, _selector(_regularWindow
|
, _selector((_regularWindow && _features.commonTabbedPanel)
|
||||||
? _regularWindow->tabbedSelector()
|
? _regularWindow->tabbedSelector()
|
||||||
: not_null(_ownedSelector.get()))
|
: not_null(_ownedSelector.get()))
|
||||||
, _mode(descriptor.mode)
|
, _mode(descriptor.mode)
|
||||||
|
@ -876,6 +885,12 @@ void ComposeControls::updateTopicRootId(MsgId topicRootId) {
|
||||||
_header->updateTopicRootId(_topicRootId);
|
_header->updateTopicRootId(_topicRootId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ComposeControls::updateShortcutId(BusinessShortcutId shortcutId) {
|
||||||
|
unregisterDraftSources();
|
||||||
|
_shortcutId = shortcutId;
|
||||||
|
registerDraftSource();
|
||||||
|
}
|
||||||
|
|
||||||
void ComposeControls::setHistory(SetHistoryArgs &&args) {
|
void ComposeControls::setHistory(SetHistoryArgs &&args) {
|
||||||
_showSlowmodeError = std::move(args.showSlowmodeError);
|
_showSlowmodeError = std::move(args.showSlowmodeError);
|
||||||
_sendActionFactory = std::move(args.sendActionFactory);
|
_sendActionFactory = std::move(args.sendActionFactory);
|
||||||
|
@ -1592,7 +1607,7 @@ void ComposeControls::initField() {
|
||||||
&& Data::AllowEmojiWithoutPremium(_history->peer, emoji);
|
&& Data::AllowEmojiWithoutPremium(_history->peer, emoji);
|
||||||
};
|
};
|
||||||
const auto suggestions = Ui::Emoji::SuggestionsController::Init(
|
const auto suggestions = Ui::Emoji::SuggestionsController::Init(
|
||||||
_parent,
|
_panelsParent,
|
||||||
_field,
|
_field,
|
||||||
_session,
|
_session,
|
||||||
{
|
{
|
||||||
|
@ -1828,6 +1843,10 @@ Data::DraftKey ComposeControls::draftKey(DraftType type) const {
|
||||||
return (type == DraftType::Edit)
|
return (type == DraftType::Edit)
|
||||||
? Key::ScheduledEdit()
|
? Key::ScheduledEdit()
|
||||||
: Key::Scheduled();
|
: Key::Scheduled();
|
||||||
|
case Section::ShortcutMessages:
|
||||||
|
return (type == DraftType::Edit)
|
||||||
|
? Key::ShortcutEdit(_shortcutId)
|
||||||
|
: Key::Shortcut(_shortcutId);
|
||||||
}
|
}
|
||||||
return Key::None();
|
return Key::None();
|
||||||
}
|
}
|
||||||
|
@ -2053,7 +2072,9 @@ rpl::producer<SendActionUpdate> ComposeControls::sendActionUpdates() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComposeControls::initTabbedSelector() {
|
void ComposeControls::initTabbedSelector() {
|
||||||
if (!_regularWindow || _regularWindow->hasTabbedSelectorOwnership()) {
|
if (!_regularWindow
|
||||||
|
|| !_features.commonTabbedPanel
|
||||||
|
|| _regularWindow->hasTabbedSelectorOwnership()) {
|
||||||
createTabbedPanel();
|
createTabbedPanel();
|
||||||
} else {
|
} else {
|
||||||
setTabbedPanel(nullptr);
|
setTabbedPanel(nullptr);
|
||||||
|
@ -2686,7 +2707,7 @@ void ComposeControls::updateAttachBotsMenu() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_attachBotsMenu = InlineBots::MakeAttachBotsMenu(
|
_attachBotsMenu = InlineBots::MakeAttachBotsMenu(
|
||||||
_parent,
|
_panelsParent,
|
||||||
_regularWindow,
|
_regularWindow,
|
||||||
_history->peer,
|
_history->peer,
|
||||||
_sendActionFactory,
|
_sendActionFactory,
|
||||||
|
@ -2729,7 +2750,7 @@ void ComposeControls::escape() {
|
||||||
bool ComposeControls::pushTabbedSelectorToThirdSection(
|
bool ComposeControls::pushTabbedSelectorToThirdSection(
|
||||||
not_null<Data::Thread*> thread,
|
not_null<Data::Thread*> thread,
|
||||||
const Window::SectionShow ¶ms) {
|
const Window::SectionShow ¶ms) {
|
||||||
if (!_tabbedPanel || !_regularWindow) {
|
if (!_tabbedPanel || !_regularWindow || !_features.commonTabbedPanel) {
|
||||||
return true;
|
return true;
|
||||||
//} else if (!_canSendMessages) {
|
//} else if (!_canSendMessages) {
|
||||||
// Core::App().settings().setTabbedReplacedWithInfo(true);
|
// Core::App().settings().setTabbedReplacedWithInfo(true);
|
||||||
|
@ -2764,7 +2785,7 @@ void ComposeControls::createTabbedPanel() {
|
||||||
.nonOwnedSelector = _ownedSelector ? nullptr : _selector.get(),
|
.nonOwnedSelector = _ownedSelector ? nullptr : _selector.get(),
|
||||||
};
|
};
|
||||||
setTabbedPanel(std::make_unique<TabbedPanel>(
|
setTabbedPanel(std::make_unique<TabbedPanel>(
|
||||||
_parent,
|
_panelsParent,
|
||||||
std::move(descriptor)));
|
std::move(descriptor)));
|
||||||
_tabbedPanel->setDesiredHeightValues(
|
_tabbedPanel->setDesiredHeightValues(
|
||||||
st::emojiPanHeightRatio,
|
st::emojiPanHeightRatio,
|
||||||
|
@ -2787,7 +2808,7 @@ void ComposeControls::setTabbedPanel(
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComposeControls::toggleTabbedSelectorMode() {
|
void ComposeControls::toggleTabbedSelectorMode() {
|
||||||
if (!_history || !_regularWindow) {
|
if (!_history || !_regularWindow || !_features.commonTabbedPanel) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_tabbedPanel) {
|
if (_tabbedPanel) {
|
||||||
|
@ -3248,7 +3269,7 @@ void ComposeControls::applyInlineBotQuery(
|
||||||
}
|
}
|
||||||
if (!_inlineResults) {
|
if (!_inlineResults) {
|
||||||
_inlineResults = std::make_unique<InlineBots::Layout::Widget>(
|
_inlineResults = std::make_unique<InlineBots::Layout::Widget>(
|
||||||
_parent,
|
_panelsParent,
|
||||||
_regularWindow);
|
_regularWindow);
|
||||||
_inlineResults->setResultSelectedCallback([=](
|
_inlineResults->setResultSelectedCallback([=](
|
||||||
InlineBots::ResultSelected result) {
|
InlineBots::ResultSelected result) {
|
||||||
|
|
|
@ -37,6 +37,7 @@ class TabbedSelector;
|
||||||
struct FileChosen;
|
struct FileChosen;
|
||||||
struct PhotoChosen;
|
struct PhotoChosen;
|
||||||
class Show;
|
class Show;
|
||||||
|
enum class PauseReason;
|
||||||
} // namespace ChatHelpers
|
} // namespace ChatHelpers
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
|
@ -95,6 +96,8 @@ enum class ComposeControlsMode {
|
||||||
Scheduled,
|
Scheduled,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern const ChatHelpers::PauseReason kDefaultPanelsLevel;
|
||||||
|
|
||||||
struct ComposeControlsDescriptor {
|
struct ComposeControlsDescriptor {
|
||||||
const style::ComposeControls *stOverride = nullptr;
|
const style::ComposeControls *stOverride = nullptr;
|
||||||
std::shared_ptr<ChatHelpers::Show> show;
|
std::shared_ptr<ChatHelpers::Show> show;
|
||||||
|
@ -104,6 +107,8 @@ struct ComposeControlsDescriptor {
|
||||||
Window::SessionController *regularWindow = nullptr;
|
Window::SessionController *regularWindow = nullptr;
|
||||||
rpl::producer<ChatHelpers::FileChosen> stickerOrEmojiChosen;
|
rpl::producer<ChatHelpers::FileChosen> stickerOrEmojiChosen;
|
||||||
rpl::producer<QString> customPlaceholder;
|
rpl::producer<QString> customPlaceholder;
|
||||||
|
QWidget *panelsParent = nullptr;
|
||||||
|
ChatHelpers::PauseReason panelsLevel = kDefaultPanelsLevel;
|
||||||
QString voiceCustomCancelText;
|
QString voiceCustomCancelText;
|
||||||
bool voiceLockFromBottom = false;
|
bool voiceLockFromBottom = false;
|
||||||
ChatHelpers::ComposeFeatures features;
|
ChatHelpers::ComposeFeatures features;
|
||||||
|
@ -137,6 +142,7 @@ public:
|
||||||
[[nodiscard]] Main::Session &session() const;
|
[[nodiscard]] Main::Session &session() const;
|
||||||
void setHistory(SetHistoryArgs &&args);
|
void setHistory(SetHistoryArgs &&args);
|
||||||
void updateTopicRootId(MsgId topicRootId);
|
void updateTopicRootId(MsgId topicRootId);
|
||||||
|
void updateShortcutId(BusinessShortcutId shortcutId);
|
||||||
void setCurrentDialogsEntryState(Dialogs::EntryState state);
|
void setCurrentDialogsEntryState(Dialogs::EntryState state);
|
||||||
[[nodiscard]] PeerData *sendAsPeer() const;
|
[[nodiscard]] PeerData *sendAsPeer() const;
|
||||||
|
|
||||||
|
@ -343,6 +349,7 @@ private:
|
||||||
const style::ComposeControls &_st;
|
const style::ComposeControls &_st;
|
||||||
const ChatHelpers::ComposeFeatures _features;
|
const ChatHelpers::ComposeFeatures _features;
|
||||||
const not_null<QWidget*> _parent;
|
const not_null<QWidget*> _parent;
|
||||||
|
const not_null<QWidget*> _panelsParent;
|
||||||
const std::shared_ptr<ChatHelpers::Show> _show;
|
const std::shared_ptr<ChatHelpers::Show> _show;
|
||||||
const not_null<Main::Session*> _session;
|
const not_null<Main::Session*> _session;
|
||||||
|
|
||||||
|
@ -353,6 +360,7 @@ private:
|
||||||
|
|
||||||
History *_history = nullptr;
|
History *_history = nullptr;
|
||||||
MsgId _topicRootId = 0;
|
MsgId _topicRootId = 0;
|
||||||
|
BusinessShortcutId _shortcutId = 0;
|
||||||
Fn<bool()> _showSlowmodeError;
|
Fn<bool()> _showSlowmodeError;
|
||||||
Fn<Api::SendAction()> _sendActionFactory;
|
Fn<Api::SendAction()> _sendActionFactory;
|
||||||
rpl::variable<int> _slowmodeSecondsLeft;
|
rpl::variable<int> _slowmodeSecondsLeft;
|
||||||
|
|
|
@ -551,7 +551,7 @@ void BottomInfo::layoutReactionsText() {
|
||||||
|
|
||||||
QSize BottomInfo::countOptimalSize() {
|
QSize BottomInfo::countOptimalSize() {
|
||||||
if (_data.flags & Data::Flag::Shortcut) {
|
if (_data.flags & Data::Flag::Shortcut) {
|
||||||
return { st::historySendStateSpace / 2, st::msgDateFont->height };
|
return { st::historyShortcutStateSpace, st::msgDateFont->height };
|
||||||
}
|
}
|
||||||
auto width = 0;
|
auto width = 0;
|
||||||
if (_data.flags & (Data::Flag::OutLayout | Data::Flag::Sending)) {
|
if (_data.flags & (Data::Flag::OutLayout | Data::Flag::Sending)) {
|
||||||
|
|
|
@ -102,7 +102,9 @@ bool HasEditMessageAction(
|
||||||
|| item->hasFailed()
|
|| item->hasFailed()
|
||||||
|| item->isEditingMedia()
|
|| item->isEditingMedia()
|
||||||
|| !request.selectedItems.empty()
|
|| !request.selectedItems.empty()
|
||||||
|| (context != Context::History && context != Context::Replies)) {
|
|| (context != Context::History
|
||||||
|
&& context != Context::Replies
|
||||||
|
&& context != Context::ShortcutMessages)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto peer = item->history()->peer;
|
const auto peer = item->history()->peer;
|
||||||
|
|
|
@ -2166,6 +2166,21 @@ void ListWidget::paintEvent(QPaintEvent *e) {
|
||||||
context.translate(0, top);
|
context.translate(0, top);
|
||||||
p.translate(0, -top);
|
p.translate(0, -top);
|
||||||
|
|
||||||
|
paintUserpics(p, context, clip);
|
||||||
|
paintDates(p, context, clip);
|
||||||
|
|
||||||
|
_reactionsManager->paint(p, context);
|
||||||
|
_emojiInteractions->paint(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListWidget::paintUserpics(
|
||||||
|
Painter &p,
|
||||||
|
const Ui::ChatPaintContext &context,
|
||||||
|
QRect clip) {
|
||||||
|
if (_context == Context::ShortcutMessages) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto session = &controller()->session();
|
||||||
enumerateUserpics([&](not_null<Element*> view, int userpicTop) {
|
enumerateUserpics([&](not_null<Element*> view, int userpicTop) {
|
||||||
// stop the enumeration if the userpic is below the painted rect
|
// stop the enumeration if the userpic is below the painted rect
|
||||||
if (userpicTop >= clip.top() + clip.height()) {
|
if (userpicTop >= clip.top() + clip.height()) {
|
||||||
|
@ -2210,6 +2225,15 @@ void ListWidget::paintEvent(QPaintEvent *e) {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListWidget::paintDates(
|
||||||
|
Painter &p,
|
||||||
|
const Ui::ChatPaintContext &context,
|
||||||
|
QRect clip) {
|
||||||
|
if (_context == Context::ShortcutMessages) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto dateHeight = st::msgServicePadding.bottom() + st::msgServiceFont->height + st::msgServicePadding.top();
|
auto dateHeight = st::msgServicePadding.bottom() + st::msgServiceFont->height + st::msgServicePadding.top();
|
||||||
auto scrollDateOpacity = _scrollDateOpacity.value(_scrollDateShown ? 1. : 0.);
|
auto scrollDateOpacity = _scrollDateOpacity.value(_scrollDateShown ? 1. : 0.);
|
||||||
|
@ -2256,9 +2280,6 @@ void ListWidget::paintEvent(QPaintEvent *e) {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
_reactionsManager->paint(p, context);
|
|
||||||
_emojiInteractions->paint(p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::maybeMarkReactionsRead(not_null<HistoryItem*> item) {
|
void ListWidget::maybeMarkReactionsRead(not_null<HistoryItem*> item) {
|
||||||
|
|
|
@ -600,6 +600,15 @@ private:
|
||||||
void showPremiumStickerTooltip(
|
void showPremiumStickerTooltip(
|
||||||
not_null<const HistoryView::Element*> view);
|
not_null<const HistoryView::Element*> view);
|
||||||
|
|
||||||
|
void paintUserpics(
|
||||||
|
Painter &p,
|
||||||
|
const Ui::ChatPaintContext &context,
|
||||||
|
QRect clip);
|
||||||
|
void paintDates(
|
||||||
|
Painter &p,
|
||||||
|
const Ui::ChatPaintContext &context,
|
||||||
|
QRect clip);
|
||||||
|
|
||||||
// This function finds all history items that are displayed and calls template method
|
// This function finds all history items that are displayed and calls template method
|
||||||
// for each found message (in given direction) in the passed history with passed top offset.
|
// for each found message (in given direction) in the passed history with passed top offset.
|
||||||
//
|
//
|
||||||
|
|
|
@ -167,7 +167,12 @@ Ui::RpWidget *ContentWidget::doSetInnerWidget(
|
||||||
const auto bottom = top + height;
|
const auto bottom = top + height;
|
||||||
_innerDesiredHeight = desired;
|
_innerDesiredHeight = desired;
|
||||||
_innerWrap->setVisibleTopBottom(top, bottom);
|
_innerWrap->setVisibleTopBottom(top, bottom);
|
||||||
|
LOG(("TOP: %1, HEIGHT: %2, DESIRED: %3, TILL: %4").arg(top).arg(height).arg(desired).arg(std::max(desired - bottom, 0)));
|
||||||
_scrollTillBottomChanges.fire_copy(std::max(desired - bottom, 0));
|
_scrollTillBottomChanges.fire_copy(std::max(desired - bottom, 0));
|
||||||
|
//const auto bottom = _scroll->scrollTop() + _scroll->height();
|
||||||
|
//_innerDesiredHeight = desired;
|
||||||
|
//_innerWrap->setVisibleTopBottom(_scroll->scrollTop(), bottom);
|
||||||
|
//_scrollTillBottomChanges.fire_copy(std::max(desired - bottom, 0));
|
||||||
}, _innerWrap->lifetime());
|
}, _innerWrap->lifetime());
|
||||||
|
|
||||||
return _innerWrap->entity();
|
return _innerWrap->entity();
|
||||||
|
@ -217,7 +222,12 @@ rpl::producer<int> ContentWidget::desiredHeightValue() const {
|
||||||
_innerWrap->entity()->desiredHeightValue(),
|
_innerWrap->entity()->desiredHeightValue(),
|
||||||
_scrollTopSkip.value(),
|
_scrollTopSkip.value(),
|
||||||
_scrollBottomSkip.value()
|
_scrollBottomSkip.value()
|
||||||
) | rpl::map(_1 + _2 + _3);
|
//) | rpl::map(_1 + _2 + _3);
|
||||||
|
) | rpl::map([=](int desired, int, int) {
|
||||||
|
return desired
|
||||||
|
+ _scrollTopSkip.current()
|
||||||
|
+ _scrollBottomSkip.current();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<bool> ContentWidget::desiredShadowVisibility() const {
|
rpl::producer<bool> ContentWidget::desiredShadowVisibility() const {
|
||||||
|
|
|
@ -30,7 +30,7 @@ LayerWidget::LayerWidget(
|
||||||
not_null<Window::SessionController*> controller,
|
not_null<Window::SessionController*> controller,
|
||||||
not_null<Memento*> memento)
|
not_null<Memento*> memento)
|
||||||
: _controller(controller)
|
: _controller(controller)
|
||||||
, _content(this, controller, Wrap::Layer, memento) {
|
, _contentWrap(this, controller, Wrap::Layer, memento) {
|
||||||
setupHeightConsumers();
|
setupHeightConsumers();
|
||||||
controller->window().replaceFloatPlayerDelegate(floatPlayerDelegate());
|
controller->window().replaceFloatPlayerDelegate(floatPlayerDelegate());
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ LayerWidget::LayerWidget(
|
||||||
not_null<Window::SessionController*> controller,
|
not_null<Window::SessionController*> controller,
|
||||||
not_null<MoveMemento*> memento)
|
not_null<MoveMemento*> memento)
|
||||||
: _controller(controller)
|
: _controller(controller)
|
||||||
, _content(memento->takeContent(this, Wrap::Layer)) {
|
, _contentWrap(memento->takeContent(this, Wrap::Layer)) {
|
||||||
setupHeightConsumers();
|
setupHeightConsumers();
|
||||||
controller->window().replaceFloatPlayerDelegate(floatPlayerDelegate());
|
controller->window().replaceFloatPlayerDelegate(floatPlayerDelegate());
|
||||||
}
|
}
|
||||||
|
@ -64,17 +64,17 @@ void LayerWidget::floatPlayerToggleGifsPaused(bool paused) {
|
||||||
|
|
||||||
auto LayerWidget::floatPlayerGetSection(Window::Column column)
|
auto LayerWidget::floatPlayerGetSection(Window::Column column)
|
||||||
-> not_null<::Media::Player::FloatSectionDelegate*> {
|
-> not_null<::Media::Player::FloatSectionDelegate*> {
|
||||||
Expects(_content != nullptr);
|
Expects(_contentWrap != nullptr);
|
||||||
|
|
||||||
return _content;
|
return _contentWrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayerWidget::floatPlayerEnumerateSections(Fn<void(
|
void LayerWidget::floatPlayerEnumerateSections(Fn<void(
|
||||||
not_null<::Media::Player::FloatSectionDelegate*> widget,
|
not_null<::Media::Player::FloatSectionDelegate*> widget,
|
||||||
Window::Column widgetColumn)> callback) {
|
Window::Column widgetColumn)> callback) {
|
||||||
Expects(_content != nullptr);
|
Expects(_contentWrap != nullptr);
|
||||||
|
|
||||||
callback(_content, Window::Column::Second);
|
callback(_contentWrap, Window::Column::Second);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LayerWidget::floatPlayerIsVisible(not_null<HistoryItem*> item) {
|
bool LayerWidget::floatPlayerIsVisible(not_null<HistoryItem*> item) {
|
||||||
|
@ -87,9 +87,9 @@ void LayerWidget::floatPlayerDoubleClickEvent(
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayerWidget::setupHeightConsumers() {
|
void LayerWidget::setupHeightConsumers() {
|
||||||
Expects(_content != nullptr);
|
Expects(_contentWrap != nullptr);
|
||||||
|
|
||||||
_content->scrollTillBottomChanges(
|
_contentWrap->scrollTillBottomChanges(
|
||||||
) | rpl::filter([this] {
|
) | rpl::filter([this] {
|
||||||
if (!_inResize) {
|
if (!_inResize) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -100,10 +100,10 @@ void LayerWidget::setupHeightConsumers() {
|
||||||
resizeToWidth(width());
|
resizeToWidth(width());
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
_content->grabbingForExpanding(
|
_contentWrap->grabbingForExpanding(
|
||||||
) | rpl::start_with_next([=](bool grabbing) {
|
) | rpl::start_with_next([=](bool grabbing) {
|
||||||
if (grabbing) {
|
if (grabbing) {
|
||||||
_savedHeight = _contentHeight;
|
_savedHeight = _contentWrapHeight;
|
||||||
_savedHeightAnimation = base::take(_heightAnimation);
|
_savedHeightAnimation = base::take(_heightAnimation);
|
||||||
setContentHeight(_desiredHeight);
|
setContentHeight(_desiredHeight);
|
||||||
} else {
|
} else {
|
||||||
|
@ -112,7 +112,7 @@ void LayerWidget::setupHeightConsumers() {
|
||||||
}
|
}
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
_content->desiredHeightValue(
|
_contentWrap->desiredHeightValue(
|
||||||
) | rpl::start_with_next([this](int height) {
|
) | rpl::start_with_next([this](int height) {
|
||||||
if (!height) {
|
if (!height) {
|
||||||
// New content arrived.
|
// New content arrived.
|
||||||
|
@ -128,32 +128,32 @@ void LayerWidget::setupHeightConsumers() {
|
||||||
_heightAnimated = true;
|
_heightAnimated = true;
|
||||||
_heightAnimation.start([=] {
|
_heightAnimation.start([=] {
|
||||||
setContentHeight(_heightAnimation.value(_desiredHeight));
|
setContentHeight(_heightAnimation.value(_desiredHeight));
|
||||||
}, _contentHeight, _desiredHeight, st::slideDuration);
|
}, _contentWrapHeight, _desiredHeight, st::slideDuration);
|
||||||
resizeToWidth(width());
|
resizeToWidth(width());
|
||||||
}
|
}
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayerWidget::setContentHeight(int height) {
|
void LayerWidget::setContentHeight(int height) {
|
||||||
if (_contentHeight == height) {
|
if (_contentWrapHeight == height) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
LOG(("CONTENT WRAP HEIGHT: %1 -> %2").arg(_contentWrapHeight).arg(height));
|
||||||
_contentHeight = height;
|
_contentWrapHeight = height;
|
||||||
if (_inResize) {
|
if (_inResize) {
|
||||||
_pendingResize = true;
|
_pendingResize = true;
|
||||||
} else if (_content) {
|
} else if (_contentWrap) {
|
||||||
resizeToWidth(width());
|
resizeToWidth(width());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayerWidget::showFinished() {
|
void LayerWidget::showFinished() {
|
||||||
floatPlayerShowVisible();
|
floatPlayerShowVisible();
|
||||||
_content->showFast();
|
_contentWrap->showFast();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayerWidget::parentResized() {
|
void LayerWidget::parentResized() {
|
||||||
if (!_content) {
|
if (!_contentWrap) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +163,7 @@ void LayerWidget::parentResized() {
|
||||||
Ui::FocusPersister persister(this);
|
Ui::FocusPersister persister(this);
|
||||||
restoreFloatPlayerDelegate();
|
restoreFloatPlayerDelegate();
|
||||||
|
|
||||||
auto memento = std::make_shared<MoveMemento>(std::move(_content));
|
auto memento = std::make_shared<MoveMemento>(std::move(_contentWrap));
|
||||||
|
|
||||||
// We want to call hideSpecialLayer synchronously to avoid glitches,
|
// We want to call hideSpecialLayer synchronously to avoid glitches,
|
||||||
// but we can't destroy LayerStackWidget from its' resizeEvent,
|
// but we can't destroy LayerStackWidget from its' resizeEvent,
|
||||||
|
@ -209,7 +209,7 @@ bool LayerWidget::takeToThirdSection() {
|
||||||
//
|
//
|
||||||
//Ui::FocusPersister persister(this);
|
//Ui::FocusPersister persister(this);
|
||||||
//auto localCopy = _controller;
|
//auto localCopy = _controller;
|
||||||
//auto memento = MoveMemento(std::move(_content));
|
//auto memento = MoveMemento(std::move(_contentWrap));
|
||||||
//localCopy->hideSpecialLayer(anim::type::instant);
|
//localCopy->hideSpecialLayer(anim::type::instant);
|
||||||
|
|
||||||
//// When creating third section in response to the window
|
//// When creating third section in response to the window
|
||||||
|
@ -235,7 +235,7 @@ bool LayerWidget::takeToThirdSection() {
|
||||||
bool LayerWidget::showSectionInternal(
|
bool LayerWidget::showSectionInternal(
|
||||||
not_null<Window::SectionMemento*> memento,
|
not_null<Window::SectionMemento*> memento,
|
||||||
const Window::SectionShow ¶ms) {
|
const Window::SectionShow ¶ms) {
|
||||||
if (_content && _content->showInternal(memento, params)) {
|
if (_contentWrap && _contentWrap->showInternal(memento, params)) {
|
||||||
if (params.activation != anim::activation::background) {
|
if (params.activation != anim::activation::background) {
|
||||||
_controller->parentController()->hideLayer();
|
_controller->parentController()->hideLayer();
|
||||||
}
|
}
|
||||||
|
@ -245,7 +245,7 @@ bool LayerWidget::showSectionInternal(
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LayerWidget::closeByOutsideClick() const {
|
bool LayerWidget::closeByOutsideClick() const {
|
||||||
return _content ? _content->closeByOutsideClick() : true;
|
return _contentWrap ? _contentWrap->closeByOutsideClick() : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int LayerWidget::MinimalSupportedWidth() {
|
int LayerWidget::MinimalSupportedWidth() {
|
||||||
|
@ -254,19 +254,48 @@ int LayerWidget::MinimalSupportedWidth() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int LayerWidget::resizeGetHeight(int newWidth) {
|
int LayerWidget::resizeGetHeight(int newWidth) {
|
||||||
if (!parentWidget() || !_content || !newWidth) {
|
if (!parentWidget() || !_contentWrap || !newWidth) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
constexpr auto kMaxAttempts = 16;
|
constexpr auto kMaxAttempts = 16;
|
||||||
auto attempts = 0;
|
auto attempts = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
_inResize = true;
|
_inResize = true;
|
||||||
|
{
|
||||||
|
const auto &parentSize = parentWidget()->size();
|
||||||
|
const auto windowWidth = parentSize.width();
|
||||||
|
const auto windowHeight = parentSize.height();
|
||||||
|
const auto newLeft = (windowWidth - newWidth) / 2;
|
||||||
|
const auto newTop = std::clamp(
|
||||||
|
windowHeight / 24,
|
||||||
|
st::infoLayerTopMinimal,
|
||||||
|
st::infoLayerTopMaximal);
|
||||||
|
const auto newBottom = newTop;
|
||||||
|
|
||||||
|
const auto bottomRadius = st::boxRadius;
|
||||||
|
const auto maxVisibleHeight = windowHeight - newTop;
|
||||||
|
// Top rounding is included in _contentWrapHeight.
|
||||||
|
auto desiredHeight = _contentWrapHeight + bottomRadius;
|
||||||
|
accumulate_min(desiredHeight, maxVisibleHeight - newBottom);
|
||||||
|
|
||||||
|
// First resize content to new width and get the new desired height.
|
||||||
|
const auto contentLeft = 0;
|
||||||
|
const auto contentTop = 0;
|
||||||
|
const auto contentBottom = bottomRadius;
|
||||||
|
const auto contentWidth = newWidth;
|
||||||
|
auto contentHeight = desiredHeight - contentTop - contentBottom;
|
||||||
|
LOG(("ATTEMPT %1: WIDTH %2, WRAP HEIGHT %3, SCROLL TILL BOTTOM: %4"
|
||||||
|
).arg(attempts + 1
|
||||||
|
).arg(newWidth
|
||||||
|
).arg(_contentWrapHeight
|
||||||
|
).arg(_contentWrap->scrollTillBottom(contentHeight)));
|
||||||
|
}
|
||||||
const auto newGeometry = countGeometry(newWidth);
|
const auto newGeometry = countGeometry(newWidth);
|
||||||
_inResize = false;
|
_inResize = false;
|
||||||
if (!_pendingResize) {
|
if (!_pendingResize) {
|
||||||
const auto oldGeometry = geometry();
|
const auto oldGeometry = geometry();
|
||||||
if (newGeometry != oldGeometry) {
|
if (newGeometry != oldGeometry) {
|
||||||
_content->forceContentRepaint();
|
_contentWrap->forceContentRepaint();
|
||||||
}
|
}
|
||||||
if (newGeometry.topLeft() != oldGeometry.topLeft()) {
|
if (newGeometry.topLeft() != oldGeometry.topLeft()) {
|
||||||
move(newGeometry.topLeft());
|
move(newGeometry.topLeft());
|
||||||
|
@ -292,8 +321,8 @@ QRect LayerWidget::countGeometry(int newWidth) {
|
||||||
|
|
||||||
const auto bottomRadius = st::boxRadius;
|
const auto bottomRadius = st::boxRadius;
|
||||||
const auto maxVisibleHeight = windowHeight - newTop;
|
const auto maxVisibleHeight = windowHeight - newTop;
|
||||||
// Top rounding is included in _contentHeight.
|
// Top rounding is included in _contentWrapHeight.
|
||||||
auto desiredHeight = _contentHeight + bottomRadius;
|
auto desiredHeight = _contentWrapHeight + bottomRadius;
|
||||||
accumulate_min(desiredHeight, maxVisibleHeight - newBottom);
|
accumulate_min(desiredHeight, maxVisibleHeight - newBottom);
|
||||||
|
|
||||||
// First resize content to new width and get the new desired height.
|
// First resize content to new width and get the new desired height.
|
||||||
|
@ -302,10 +331,11 @@ QRect LayerWidget::countGeometry(int newWidth) {
|
||||||
const auto contentBottom = bottomRadius;
|
const auto contentBottom = bottomRadius;
|
||||||
const auto contentWidth = newWidth;
|
const auto contentWidth = newWidth;
|
||||||
auto contentHeight = desiredHeight - contentTop - contentBottom;
|
auto contentHeight = desiredHeight - contentTop - contentBottom;
|
||||||
const auto scrollTillBottom = _content->scrollTillBottom(contentHeight);
|
const auto scrollTillBottom = _contentWrap->scrollTillBottom(
|
||||||
|
contentHeight);
|
||||||
auto additionalScroll = std::min(scrollTillBottom, newBottom);
|
auto additionalScroll = std::min(scrollTillBottom, newBottom);
|
||||||
|
|
||||||
const auto expanding = (_desiredHeight > _contentHeight);
|
const auto expanding = (_desiredHeight > _contentWrapHeight);
|
||||||
|
|
||||||
desiredHeight += additionalScroll;
|
desiredHeight += additionalScroll;
|
||||||
contentHeight += additionalScroll;
|
contentHeight += additionalScroll;
|
||||||
|
@ -313,11 +343,11 @@ QRect LayerWidget::countGeometry(int newWidth) {
|
||||||
if (_tillBottom) {
|
if (_tillBottom) {
|
||||||
additionalScroll += contentBottom;
|
additionalScroll += contentBottom;
|
||||||
}
|
}
|
||||||
_contentTillBottom = _tillBottom && !_content->scrollBottomSkip();
|
_contentTillBottom = _tillBottom && !_contentWrap->scrollBottomSkip();
|
||||||
if (_contentTillBottom) {
|
if (_contentTillBottom) {
|
||||||
contentHeight += contentBottom;
|
contentHeight += contentBottom;
|
||||||
}
|
}
|
||||||
_content->updateGeometry({
|
_contentWrap->updateGeometry({
|
||||||
contentLeft,
|
contentLeft,
|
||||||
contentTop,
|
contentTop,
|
||||||
contentWidth,
|
contentWidth,
|
||||||
|
@ -328,8 +358,8 @@ QRect LayerWidget::countGeometry(int newWidth) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayerWidget::doSetInnerFocus() {
|
void LayerWidget::doSetInnerFocus() {
|
||||||
if (_content) {
|
if (_contentWrap) {
|
||||||
_content->setInnerFocus();
|
_contentWrap->setInnerFocus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,7 +372,7 @@ void LayerWidget::paintEvent(QPaintEvent *e) {
|
||||||
if (!_tillBottom) {
|
if (!_tillBottom) {
|
||||||
const auto bottom = QRect{ 0, height() - radius, width(), radius };
|
const auto bottom = QRect{ 0, height() - radius, width(), radius };
|
||||||
if (clip.intersects(bottom)) {
|
if (clip.intersects(bottom)) {
|
||||||
if (const auto rounding = _content->bottomSkipRounding()) {
|
if (const auto rounding = _contentWrap->bottomSkipRounding()) {
|
||||||
rounding->paint(p, rect(), RectPart::FullBottom);
|
rounding->paint(p, rect(), RectPart::FullBottom);
|
||||||
} else {
|
} else {
|
||||||
Ui::FillRoundRect(p, bottom, st::boxBg, {
|
Ui::FillRoundRect(p, bottom, st::boxBg, {
|
||||||
|
@ -351,11 +381,11 @@ void LayerWidget::paintEvent(QPaintEvent *e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!_contentTillBottom) {
|
} else if (!_contentTillBottom) {
|
||||||
const auto rounding = _content->bottomSkipRounding();
|
const auto rounding = _contentWrap->bottomSkipRounding();
|
||||||
const auto &color = rounding ? rounding->color() : st::boxBg;
|
const auto &color = rounding ? rounding->color() : st::boxBg;
|
||||||
p.fillRect(0, height() - radius, width(), radius, color);
|
p.fillRect(0, height() - radius, width(), radius, color);
|
||||||
}
|
}
|
||||||
if (_content->animatingShow()) {
|
if (_contentWrap->animatingShow()) {
|
||||||
const auto top = QRect{ 0, 0, width(), radius };
|
const auto top = QRect{ 0, 0, width(), radius };
|
||||||
if (clip.intersects(top)) {
|
if (clip.intersects(top)) {
|
||||||
Ui::FillRoundRect(p, top, st::boxBg, {
|
Ui::FillRoundRect(p, top, st::boxBg, {
|
||||||
|
|
|
@ -73,10 +73,10 @@ private:
|
||||||
[[nodiscard]] QRect countGeometry(int newWidth);
|
[[nodiscard]] QRect countGeometry(int newWidth);
|
||||||
|
|
||||||
not_null<Window::SessionController*> _controller;
|
not_null<Window::SessionController*> _controller;
|
||||||
object_ptr<WrapWidget> _content;
|
object_ptr<WrapWidget> _contentWrap;
|
||||||
|
|
||||||
int _desiredHeight = 0;
|
int _desiredHeight = 0;
|
||||||
int _contentHeight = 0;
|
int _contentWrapHeight = 0;
|
||||||
int _savedHeight = 0;
|
int _savedHeight = 0;
|
||||||
Ui::Animations::Simple _heightAnimation;
|
Ui::Animations::Simple _heightAnimation;
|
||||||
Ui::Animations::Simple _savedHeightAnimation;
|
Ui::Animations::Simple _savedHeightAnimation;
|
||||||
|
|
|
@ -50,8 +50,8 @@ void SectionWidget::init() {
|
||||||
return (_content != nullptr);
|
return (_content != nullptr);
|
||||||
}) | rpl::start_with_next([=](QSize size, int) {
|
}) | rpl::start_with_next([=](QSize size, int) {
|
||||||
const auto expanding = false;
|
const auto expanding = false;
|
||||||
const auto additionalScroll = st::boxRadius;
|
|
||||||
const auto full = !_content->scrollBottomSkip();
|
const auto full = !_content->scrollBottomSkip();
|
||||||
|
const auto additionalScroll = (full ? st::boxRadius : 0);
|
||||||
const auto height = size.height() - (full ? 0 : st::boxRadius);
|
const auto height = size.height() - (full ? 0 : st::boxRadius);
|
||||||
const auto wrapGeometry = QRect{ 0, 0, size.width(), height };
|
const auto wrapGeometry = QRect{ 0, 0, size.width(), height };
|
||||||
_content->updateGeometry(
|
_content->updateGeometry(
|
||||||
|
|
|
@ -117,17 +117,17 @@ Widget::Widget(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_pinnedToBottom) {
|
if (_pinnedToBottom) {
|
||||||
const auto processHeight = [=](int bottomHeight, int height) {
|
const auto processHeight = [=] {
|
||||||
setScrollBottomSkip(bottomHeight);
|
setScrollBottomSkip(_pinnedToBottom->height());
|
||||||
_pinnedToBottom->moveToLeft(
|
_pinnedToBottom->moveToLeft(
|
||||||
_pinnedToBottom->x(),
|
_pinnedToBottom->x(),
|
||||||
height - bottomHeight);
|
height() - _pinnedToBottom->height());
|
||||||
};
|
};
|
||||||
|
|
||||||
_inner->sizeValue(
|
_inner->sizeValue(
|
||||||
) | rpl::start_with_next([=](const QSize &s) {
|
) | rpl::start_with_next([=](const QSize &s) {
|
||||||
_pinnedToBottom->resizeToWidth(s.width());
|
_pinnedToBottom->resizeToWidth(s.width());
|
||||||
processHeight(_pinnedToBottom->height(), height());
|
//processHeight();
|
||||||
}, _pinnedToBottom->lifetime());
|
}, _pinnedToBottom->lifetime());
|
||||||
|
|
||||||
rpl::combine(
|
rpl::combine(
|
||||||
|
|
|
@ -98,6 +98,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void outerResized(QSize outer);
|
void outerResized(QSize outer);
|
||||||
|
void updateComposeControlsPosition();
|
||||||
|
|
||||||
// ListDelegate interface.
|
// ListDelegate interface.
|
||||||
Context listContext() override;
|
Context listContext() override;
|
||||||
|
@ -505,7 +506,7 @@ void ShortcutMessages::outerResized(QSize outer) {
|
||||||
? base::make_optional(_scroll->scrollTop())
|
? base::make_optional(_scroll->scrollTop())
|
||||||
: 0;
|
: 0;
|
||||||
_skipScrollEvent = true;
|
_skipScrollEvent = true;
|
||||||
_inner->resizeToWidth(contentWidth, _scroll->height());
|
_inner->resizeToWidth(contentWidth, st::boxWidth);
|
||||||
_skipScrollEvent = false;
|
_skipScrollEvent = false;
|
||||||
|
|
||||||
if (!_scroll->isHidden()) {
|
if (!_scroll->isHidden()) {
|
||||||
|
@ -514,25 +515,34 @@ void ShortcutMessages::outerResized(QSize outer) {
|
||||||
}
|
}
|
||||||
updateInnerVisibleArea();
|
updateInnerVisibleArea();
|
||||||
}
|
}
|
||||||
_composeControls->setAutocompleteBoundingRect(_scroll->geometry());
|
updateComposeControlsPosition();
|
||||||
_cornerButtons.updatePositions();
|
_cornerButtons.updatePositions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShortcutMessages::updateComposeControlsPosition() {
|
||||||
|
const auto bottom = _scroll->parentWidget()->height();
|
||||||
|
const auto controlsHeight = _composeControls->heightCurrent();
|
||||||
|
_composeControls->move(0, bottom - controlsHeight + st::boxRadius);
|
||||||
|
_composeControls->setAutocompleteBoundingRect(_scroll->geometry());
|
||||||
|
}
|
||||||
|
|
||||||
void ShortcutMessages::setupComposeControls() {
|
void ShortcutMessages::setupComposeControls() {
|
||||||
|
_shortcutId.value() | rpl::start_with_next([=](BusinessShortcutId id) {
|
||||||
|
_composeControls->updateShortcutId(id);
|
||||||
|
}, lifetime());
|
||||||
|
|
||||||
|
const auto state = Dialogs::EntryState{
|
||||||
|
.key = Dialogs::Key{ _history },
|
||||||
|
.section = Dialogs::EntryState::Section::ShortcutMessages,
|
||||||
|
.currentReplyTo = replyTo(),
|
||||||
|
};
|
||||||
|
_composeControls->setCurrentDialogsEntryState(state);
|
||||||
|
|
||||||
_composeControls->setHistory({
|
_composeControls->setHistory({
|
||||||
.history = _history.get(),
|
.history = _history.get(),
|
||||||
.writeRestriction = rpl::single(Controls::WriteRestriction()),
|
.writeRestriction = rpl::single(Controls::WriteRestriction()),
|
||||||
});
|
});
|
||||||
|
|
||||||
_composeControls->height(
|
|
||||||
) | rpl::start_with_next([=](int height) {
|
|
||||||
const auto wasMax = (_scroll->scrollTopMax() == _scroll->scrollTop());
|
|
||||||
_controlsWrap->resize(width(), height);
|
|
||||||
if (wasMax) {
|
|
||||||
listScrollTo(_scroll->scrollTopMax());
|
|
||||||
}
|
|
||||||
}, lifetime());
|
|
||||||
|
|
||||||
_composeControls->cancelRequests(
|
_composeControls->cancelRequests(
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
listCancelRequest();
|
listCancelRequest();
|
||||||
|
@ -637,20 +647,58 @@ void ShortcutMessages::setupComposeControls() {
|
||||||
_controlsWrap->widthValue() | rpl::start_with_next([=](int width) {
|
_controlsWrap->widthValue() | rpl::start_with_next([=](int width) {
|
||||||
_composeControls->resizeToWidth(width);
|
_composeControls->resizeToWidth(width);
|
||||||
}, _controlsWrap->lifetime());
|
}, _controlsWrap->lifetime());
|
||||||
_composeControls->height() | rpl::start_with_next([=](int height) {
|
|
||||||
_controlsWrap->resize(_controlsWrap->width(), height);
|
_composeControls->height(
|
||||||
}, _controlsWrap->lifetime());
|
) | rpl::start_with_next([=](int height) {
|
||||||
|
const auto wasMax = (_scroll->scrollTopMax() == _scroll->scrollTop());
|
||||||
|
_controlsWrap->resize(width(), height - st::boxRadius);
|
||||||
|
updateComposeControlsPosition();
|
||||||
|
if (wasMax) {
|
||||||
|
listScrollTo(_scroll->scrollTopMax());
|
||||||
|
}
|
||||||
|
}, lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
QPointer<Ui::RpWidget> ShortcutMessages::createPinnedToBottom(
|
QPointer<Ui::RpWidget> ShortcutMessages::createPinnedToBottom(
|
||||||
not_null<Ui::RpWidget*> parent) {
|
not_null<Ui::RpWidget*> parent) {
|
||||||
|
auto placeholder = rpl::deferred([=] {
|
||||||
|
return _shortcutId.value();
|
||||||
|
}) | rpl::map([=](BusinessShortcutId id) {
|
||||||
|
return _session->data().shortcutMessages().lookupShortcut(id).name;
|
||||||
|
}) | rpl::map([=](const QString &shortcut) {
|
||||||
|
return (shortcut == u"away"_q)
|
||||||
|
? tr::lng_away_message_placeholder()
|
||||||
|
: (shortcut == u"hello"_q)
|
||||||
|
? tr::lng_greeting_message_placeholder()
|
||||||
|
: tr::lng_replies_message_placeholder();
|
||||||
|
}) | rpl::flatten_latest();
|
||||||
|
|
||||||
_controlsWrap = std::make_unique<Ui::RpWidget>(parent);
|
_controlsWrap = std::make_unique<Ui::RpWidget>(parent);
|
||||||
_composeControls = std::make_unique<ComposeControls>(
|
_composeControls = std::make_unique<ComposeControls>(
|
||||||
_controlsWrap.get(),
|
dynamic_cast<Ui::RpWidget*>(_scroll->parentWidget()),
|
||||||
_controller,
|
ComposeControlsDescriptor{
|
||||||
[=](not_null<DocumentData*> emoji) { listShowPremiumToast(emoji); },
|
.show = _controller->uiShow(),
|
||||||
ComposeControls::Mode::Normal,
|
.unavailableEmojiPasted = [=](not_null<DocumentData*> emoji) {
|
||||||
SendMenu::Type::Disabled);
|
listShowPremiumToast(emoji);
|
||||||
|
},
|
||||||
|
.mode = HistoryView::ComposeControlsMode::Normal,
|
||||||
|
.sendMenuType = SendMenu::Type::Disabled,
|
||||||
|
.regularWindow = _controller,
|
||||||
|
.stickerOrEmojiChosen = _controller->stickerOrEmojiChosen(),
|
||||||
|
.customPlaceholder = std::move(placeholder),
|
||||||
|
.panelsLevel = Window::GifPauseReason::Layer,
|
||||||
|
.voiceCustomCancelText = tr::lng_record_cancel_stories(tr::now),
|
||||||
|
.voiceLockFromBottom = true,
|
||||||
|
.features = {
|
||||||
|
.sendAs = false,
|
||||||
|
.ttlInfo = false,
|
||||||
|
.botCommandSend = false,
|
||||||
|
.silentBroadcastToggle = false,
|
||||||
|
.attachBotsMenu = false,
|
||||||
|
.megagroupSet = false,
|
||||||
|
.commonTabbedPanel = false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
setupComposeControls();
|
setupComposeControls();
|
||||||
|
|
||||||
|
|
|
@ -517,6 +517,7 @@ FileLoadTask::FileLoadTask(
|
||||||
, _caption(caption)
|
, _caption(caption)
|
||||||
, _spoiler(spoiler) {
|
, _spoiler(spoiler) {
|
||||||
Expects(to.options.scheduled
|
Expects(to.options.scheduled
|
||||||
|
|| to.options.shortcutId
|
||||||
|| !to.replaceMediaOf
|
|| !to.replaceMediaOf
|
||||||
|| IsServerMsgId(to.replaceMediaOf));
|
|| IsServerMsgId(to.replaceMediaOf));
|
||||||
|
|
||||||
|
|
|
@ -301,6 +301,7 @@ historySentInvertedIcon: icon {{ "history_sent", historyIconFgInverted, point(2p
|
||||||
historyReceivedIcon: icon {{ "history_received", historyOutIconFg, point(2px, 4px) }};
|
historyReceivedIcon: icon {{ "history_received", historyOutIconFg, point(2px, 4px) }};
|
||||||
historyReceivedSelectedIcon: icon {{ "history_received", historyOutIconFgSelected, point(2px, 4px) }};
|
historyReceivedSelectedIcon: icon {{ "history_received", historyOutIconFgSelected, point(2px, 4px) }};
|
||||||
historyReceivedInvertedIcon: icon {{ "history_received", historyIconFgInverted, point(2px, 4px) }};
|
historyReceivedInvertedIcon: icon {{ "history_received", historyIconFgInverted, point(2px, 4px) }};
|
||||||
|
historyShortcutStateSpace: 18px;
|
||||||
|
|
||||||
historyViewsSpace: 8px;
|
historyViewsSpace: 8px;
|
||||||
historyViewsWidth: 20px;
|
historyViewsWidth: 20px;
|
||||||
|
|
Loading…
Add table
Reference in a new issue