mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2026-07-25 06:54:43 +00:00
251 lines
6.6 KiB
C++
251 lines
6.6 KiB
C++
/*
|
|
This file is part of Telegram Desktop,
|
|
the official desktop application for the Telegram messaging service.
|
|
|
|
For license and copyright information please follow this link:
|
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|
*/
|
|
#include "calls/group/calls_group_message_field.h"
|
|
|
|
#include "boxes/premium_preview_box.h"
|
|
#include "chat_helpers/compose/compose_show.h"
|
|
#include "chat_helpers/emoji_suggestions_widget.h"
|
|
#include "chat_helpers/message_field.h"
|
|
#include "chat_helpers/tabbed_panel.h"
|
|
#include "chat_helpers/tabbed_selector.h"
|
|
#include "data/stickers/data_custom_emoji.h"
|
|
#include "data/stickers/data_stickers.h"
|
|
#include "data/data_document.h"
|
|
#include "lang/lang_keys.h"
|
|
#include "main/main_session.h"
|
|
#include "ui/controls/emoji_button.h"
|
|
#include "ui/controls/send_button.h"
|
|
#include "ui/widgets/fields/input_field.h"
|
|
#include "ui/painter.h"
|
|
#include "ui/ui_utility.h"
|
|
#include "styles/style_chat_helpers.h"
|
|
#include "styles/style_chat.h"
|
|
#include "styles/style_media_view.h"
|
|
|
|
namespace Calls::Group {
|
|
|
|
MessageField::MessageField(
|
|
not_null<QWidget*> parent,
|
|
std::shared_ptr<ChatHelpers::Show> show,
|
|
PeerData *peer)
|
|
: _parent(parent)
|
|
, _show(std::move(show))
|
|
, _wrap(std::make_unique<Ui::RpWidget>(_parent)) {
|
|
createControls(peer);
|
|
}
|
|
|
|
void MessageField::createControls(PeerData *peer) {
|
|
setupBackground();
|
|
|
|
const auto &st = st::storiesComposeControls;
|
|
_field = Ui::CreateChild<Ui::InputField>(
|
|
_wrap.get(),
|
|
st.field,
|
|
Ui::InputField::Mode::MultiLine,
|
|
tr::lng_message_ph());
|
|
_field->setMinHeight(
|
|
st::historySendSize.height() - 2 * st::historySendPadding);
|
|
_field->setMaxHeight(st::historyComposeFieldMaxHeight);
|
|
_field->setDocumentMargin(4.);
|
|
_field->setAdditionalMargin(style::ConvertScale(4) - 4);
|
|
|
|
const auto show = _show;
|
|
const auto allow = [=](not_null<DocumentData*> emoji) {
|
|
return peer
|
|
? Data::AllowEmojiWithoutPremium(peer, emoji)
|
|
: show->session().premium();
|
|
};
|
|
InitMessageFieldHandlers({
|
|
.session = &show->session(),
|
|
.show = show,
|
|
.field = _field,
|
|
.customEmojiPaused = [=] {
|
|
return show->paused(ChatHelpers::PauseReason::Layer);
|
|
},
|
|
.allowPremiumEmoji = allow,
|
|
.fieldStyle = &st.files.caption,
|
|
});
|
|
Ui::Emoji::SuggestionsController::Init(
|
|
_parent,
|
|
_field,
|
|
&_show->session(),
|
|
{
|
|
.suggestCustomEmoji = true,
|
|
.allowCustomWithoutPremium = allow,
|
|
.st = &st.suggestions,
|
|
});
|
|
|
|
_send = Ui::CreateChild<Ui::SendButton>(_wrap.get(), st.send);
|
|
|
|
using Selector = ChatHelpers::TabbedSelector;
|
|
using Descriptor = ChatHelpers::TabbedPanelDescriptor;
|
|
_emojiPanel = Ui::CreateChild<ChatHelpers::TabbedPanel>(
|
|
_parent,
|
|
ChatHelpers::TabbedPanelDescriptor{
|
|
.ownedSelector = object_ptr<Selector>(
|
|
nullptr,
|
|
ChatHelpers::TabbedSelectorDescriptor{
|
|
.show = _show,
|
|
.st = st.tabbed,
|
|
.level = ChatHelpers::PauseReason::Layer,
|
|
.mode = ChatHelpers::TabbedSelector::Mode::EmojiOnly,
|
|
.features = {
|
|
.stickersSettings = false,
|
|
.openStickerSets = false,
|
|
},
|
|
}),
|
|
});
|
|
_emojiPanel->setDesiredHeightValues(
|
|
1.,
|
|
st::emojiPanMinHeight / 2,
|
|
st::emojiPanMinHeight);
|
|
_emojiPanel->hide();
|
|
_emojiPanel->selector()->setCurrentPeer(peer);
|
|
_emojiPanel->selector()->emojiChosen(
|
|
) | rpl::start_with_next([=](ChatHelpers::EmojiChosen data) {
|
|
Ui::InsertEmojiAtCursor(_field->textCursor(), data.emoji);
|
|
}, lifetime());
|
|
_emojiPanel->selector()->customEmojiChosen(
|
|
) | rpl::start_with_next([=](ChatHelpers::FileChosen data) {
|
|
const auto info = data.document->sticker();
|
|
if (info
|
|
&& info->setType == Data::StickersType::Emoji
|
|
&& !_show->session().premium()) {
|
|
ShowPremiumPreviewBox(
|
|
_show,
|
|
PremiumFeature::AnimatedEmoji);
|
|
} else {
|
|
Data::InsertCustomEmoji(_field, data.document);
|
|
}
|
|
}, lifetime());
|
|
|
|
_emojiToggle = Ui::CreateChild<Ui::EmojiButton>(_wrap.get(), st.emoji);
|
|
|
|
_emojiToggle->installEventFilter(_emojiPanel);
|
|
_emojiToggle->addClickHandler([=] {
|
|
_emojiPanel->toggleAnimated();
|
|
});
|
|
|
|
_width.value(
|
|
) | rpl::filter(
|
|
rpl::mappers::_1 > 0
|
|
) | rpl::start_with_next([=](int newWidth) {
|
|
_wrap->resizeToWidth(newWidth);
|
|
|
|
const auto fieldWidth = newWidth
|
|
- st::historySendPadding
|
|
- _emojiToggle->width()
|
|
- _send->width();
|
|
_field->resizeToWidth(fieldWidth);
|
|
_field->moveToLeft(
|
|
st::historySendPadding,
|
|
st::historySendPadding,
|
|
newWidth);
|
|
_send->moveToRight(0, 0);
|
|
_emojiToggle->moveToRight(_send->width(), 0);
|
|
}, _lifetime);
|
|
|
|
_field->heightValue() | rpl::start_with_next([=](int height) {
|
|
_wrap->resize(_wrap->width(), height + 2 * st::historySendPadding);
|
|
}, _lifetime);
|
|
|
|
rpl::merge(
|
|
_field->submits() | rpl::to_empty,
|
|
_send->clicks() | rpl::to_empty
|
|
) | rpl::start_with_next([=] {
|
|
_submitted.fire(_field->getTextWithAppliedMarkdown());
|
|
}, _lifetime);
|
|
}
|
|
|
|
void MessageField::updateEmojiPanelGeometry() {
|
|
const auto parent = _emojiPanel->parentWidget();
|
|
const auto global = _emojiToggle->mapToGlobal({ 0, 0 });
|
|
const auto local = parent->mapFromGlobal(global);
|
|
_emojiPanel->moveBottomRight(
|
|
local.y(),
|
|
local.x() + _emojiToggle->width() * 3);
|
|
}
|
|
|
|
void MessageField::setupBackground() {
|
|
_wrap->paintRequest() | rpl::start_with_next([=] {
|
|
const auto radius = st::historySendSize.height() / 2.;
|
|
auto p = QPainter(_wrap.get());
|
|
auto hq = PainterHighQualityEnabler(p);
|
|
|
|
p.setPen(Qt::NoPen);
|
|
p.setBrush(st::storiesComposeBg);
|
|
p.drawRoundedRect(_wrap->rect(), radius, radius);
|
|
}, _lifetime);
|
|
}
|
|
|
|
void MessageField::resizeToWidth(int newWidth) {
|
|
_width = newWidth;
|
|
if (_wrap->isHidden()) {
|
|
Ui::SendPendingMoveResizeEvents(_wrap.get());
|
|
}
|
|
updateEmojiPanelGeometry();
|
|
}
|
|
|
|
void MessageField::move(int x, int y) {
|
|
_wrap->move(x, y);
|
|
}
|
|
|
|
void MessageField::toggle(bool shown) {
|
|
if (_shown == shown) {
|
|
return;
|
|
} else if (shown) {
|
|
Assert(_width.current() > 0);
|
|
Ui::SendPendingMoveResizeEvents(_wrap.get());
|
|
}
|
|
_shown = shown;
|
|
shownAnimationCallback();
|
|
//_shownAnimation.start(
|
|
// [=] { shownAnimationCallback(); },
|
|
// shown ? 0. : 1.,
|
|
// shown ? 1. : 0.,
|
|
// st::slideWrapDuration,
|
|
// anim::easeOutCirc);
|
|
}
|
|
|
|
void MessageField::raise() {
|
|
_wrap->raise();
|
|
}
|
|
|
|
void MessageField::shownAnimationCallback() {
|
|
if (_shownAnimation.animating()) {
|
|
_wrap->update();
|
|
} else if (_shown) {
|
|
_wrap->show();
|
|
_field->setFocusFast();
|
|
} else {
|
|
_closed.fire({});
|
|
}
|
|
}
|
|
|
|
int MessageField::height() const {
|
|
return _shownAnimation.value(_shown ? 1. : 0.) * _wrap->height();
|
|
}
|
|
|
|
rpl::producer<int> MessageField::heightValue() const {
|
|
return _wrap->heightValue();
|
|
}
|
|
|
|
rpl::producer<TextWithTags> MessageField::submitted() const {
|
|
return _submitted.events();
|
|
}
|
|
|
|
rpl::producer<> MessageField::closed() const {
|
|
return _closed.events();
|
|
}
|
|
|
|
rpl::lifetime &MessageField::lifetime() {
|
|
return _lifetime;
|
|
}
|
|
|
|
} // namespace Calls::Group
|