mirror of https://github.com/procxx/kepka.git
Add a comment field to ShareBox.
This commit is contained in:
parent
65b2db2160
commit
5f665b8ecb
|
@ -402,6 +402,21 @@ shareNameTop: 6px;
|
||||||
shareColumnSkip: 6px;
|
shareColumnSkip: 6px;
|
||||||
shareActivateDuration: 150;
|
shareActivateDuration: 150;
|
||||||
shareScrollDuration: 300;
|
shareScrollDuration: 300;
|
||||||
|
shareComment: InputField(defaultInputField) {
|
||||||
|
font: normalFont;
|
||||||
|
textMargins: margins(8px, 8px, 8px, 6px);
|
||||||
|
heightMin: 36px;
|
||||||
|
heightMax: 72px;
|
||||||
|
placeholderFg: placeholderFg;
|
||||||
|
placeholderFgActive: placeholderFgActive;
|
||||||
|
placeholderFgError: placeholderFgActive;
|
||||||
|
placeholderMargins: margins(2px, 0px, 2px, 0px);
|
||||||
|
placeholderScale: 0.;
|
||||||
|
placeholderFont: normalFont;
|
||||||
|
border: 0px;
|
||||||
|
borderActive: 0px;
|
||||||
|
}
|
||||||
|
shareCommentPadding: margins(5px, 5px, 5px, 5px);
|
||||||
|
|
||||||
notificationsBoxMonitor: icon {{ "monitor", notificationsBoxMonitorFg }};
|
notificationsBoxMonitor: icon {{ "monitor", notificationsBoxMonitorFg }};
|
||||||
notificationsBoxScreenTop: 10px;
|
notificationsBoxScreenTop: 10px;
|
||||||
|
|
|
@ -215,8 +215,7 @@ EditCaptionBox::EditCaptionBox(
|
||||||
_field->setInstantReplaces(Ui::InstantReplaces::Default());
|
_field->setInstantReplaces(Ui::InstantReplaces::Default());
|
||||||
_field->setInstantReplacesEnabled(Global::ReplaceEmojiValue());
|
_field->setInstantReplacesEnabled(Global::ReplaceEmojiValue());
|
||||||
_field->setMarkdownReplacesEnabled(rpl::single(true));
|
_field->setMarkdownReplacesEnabled(rpl::single(true));
|
||||||
_field->setEditLinkCallback(
|
_field->setEditLinkCallback(DefaultEditLinkCallback(_field));
|
||||||
DefaultEditLinkCallback(_controller, _field));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditCaptionBox::prepareGifPreview(not_null<DocumentData*> document) {
|
void EditCaptionBox::prepareGifPreview(not_null<DocumentData*> document) {
|
||||||
|
|
|
@ -1582,8 +1582,7 @@ void SendFilesBox::setupCaption() {
|
||||||
_caption->setInstantReplaces(Ui::InstantReplaces::Default());
|
_caption->setInstantReplaces(Ui::InstantReplaces::Default());
|
||||||
_caption->setInstantReplacesEnabled(Global::ReplaceEmojiValue());
|
_caption->setInstantReplacesEnabled(Global::ReplaceEmojiValue());
|
||||||
_caption->setMarkdownReplacesEnabled(rpl::single(true));
|
_caption->setMarkdownReplacesEnabled(rpl::single(true));
|
||||||
_caption->setEditLinkCallback(
|
_caption->setEditLinkCallback(DefaultEditLinkCallback(_caption));
|
||||||
DefaultEditLinkCallback(_controller, _caption));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendFilesBox::captionResized() {
|
void SendFilesBox::captionResized() {
|
||||||
|
|
|
@ -8,8 +8,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "boxes/share_box.h"
|
#include "boxes/share_box.h"
|
||||||
|
|
||||||
#include "dialogs/dialogs_indexed_list.h"
|
#include "dialogs/dialogs_indexed_list.h"
|
||||||
#include "styles/style_boxes.h"
|
|
||||||
#include "styles/style_history.h"
|
|
||||||
#include "observer_peer.h"
|
#include "observer_peer.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
@ -22,7 +20,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/widgets/multi_select.h"
|
#include "ui/widgets/multi_select.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
#include "ui/widgets/scroll_area.h"
|
#include "ui/widgets/scroll_area.h"
|
||||||
|
#include "ui/widgets/input_fields.h"
|
||||||
|
#include "ui/wrap/slide_wrap.h"
|
||||||
#include "ui/text_options.h"
|
#include "ui/text_options.h"
|
||||||
|
#include "chat_helpers/message_field.h"
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
#include "history/history_media_types.h"
|
#include "history/history_media_types.h"
|
||||||
#include "history/history_message.h"
|
#include "history/history_message.h"
|
||||||
|
@ -30,69 +31,248 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "boxes/peer_list_box.h"
|
#include "boxes/peer_list_box.h"
|
||||||
#include "auth_session.h"
|
#include "auth_session.h"
|
||||||
#include "messenger.h"
|
#include "messenger.h"
|
||||||
|
#include "styles/style_boxes.h"
|
||||||
|
#include "styles/style_history.h"
|
||||||
|
|
||||||
ShareBox::ShareBox(QWidget*, CopyCallback &©Callback, SubmitCallback &&submitCallback, FilterCallback &&filterCallback)
|
|
||||||
|
class ShareBox::Inner
|
||||||
|
: public Ui::RpWidget
|
||||||
|
, public RPCSender
|
||||||
|
, private base::Subscriber {
|
||||||
|
public:
|
||||||
|
Inner(QWidget *parent, ShareBox::FilterCallback &&filterCallback);
|
||||||
|
|
||||||
|
void setPeerSelectedChangedCallback(
|
||||||
|
Fn<void(PeerData *peer, bool selected)> callback);
|
||||||
|
void peerUnselected(not_null<PeerData*> peer);
|
||||||
|
|
||||||
|
QVector<PeerData*> selected() const;
|
||||||
|
bool hasSelected() const;
|
||||||
|
|
||||||
|
void peopleReceived(
|
||||||
|
const QString &query,
|
||||||
|
const QVector<MTPPeer> &my,
|
||||||
|
const QVector<MTPPeer> &people);
|
||||||
|
|
||||||
|
void activateSkipRow(int direction);
|
||||||
|
void activateSkipColumn(int direction);
|
||||||
|
void activateSkipPage(int pageHeight, int direction);
|
||||||
|
void updateFilter(QString filter = QString());
|
||||||
|
void selectActive();
|
||||||
|
|
||||||
|
rpl::producer<Ui::ScrollToRequest> scrollToRequests() const;
|
||||||
|
rpl::producer<> searchRequests() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void visibleTopBottomUpdated(
|
||||||
|
int visibleTop,
|
||||||
|
int visibleBottom) override;
|
||||||
|
|
||||||
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
void enterEventHook(QEvent *e) override;
|
||||||
|
void leaveEventHook(QEvent *e) override;
|
||||||
|
void mouseMoveEvent(QMouseEvent *e) override;
|
||||||
|
void mousePressEvent(QMouseEvent *e) override;
|
||||||
|
void resizeEvent(QResizeEvent *e) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Chat {
|
||||||
|
Chat(PeerData *peer, Fn<void()> updateCallback);
|
||||||
|
|
||||||
|
PeerData *peer;
|
||||||
|
Ui::RoundImageCheckbox checkbox;
|
||||||
|
Text name;
|
||||||
|
Animation nameActive;
|
||||||
|
};
|
||||||
|
|
||||||
|
void notifyPeerUpdated(const Notify::PeerUpdate &update);
|
||||||
|
void invalidateCache();
|
||||||
|
|
||||||
|
int displayedChatsCount() const;
|
||||||
|
|
||||||
|
void paintChat(Painter &p, TimeMs ms, not_null<Chat*> chat, int index);
|
||||||
|
void updateChat(not_null<PeerData*> peer);
|
||||||
|
void updateChatName(not_null<Chat*> chat, not_null<PeerData*> peer);
|
||||||
|
void repaintChat(not_null<PeerData*> peer);
|
||||||
|
int chatIndex(not_null<PeerData*> peer) const;
|
||||||
|
void repaintChatAtIndex(int index);
|
||||||
|
Chat *getChatAtIndex(int index);
|
||||||
|
|
||||||
|
void loadProfilePhotos(int yFrom);
|
||||||
|
void changeCheckState(Chat *chat);
|
||||||
|
enum class ChangeStateWay {
|
||||||
|
Default,
|
||||||
|
SkipCallback,
|
||||||
|
};
|
||||||
|
void changePeerCheckState(
|
||||||
|
not_null<Chat*> chat,
|
||||||
|
bool checked,
|
||||||
|
ChangeStateWay useCallback = ChangeStateWay::Default);
|
||||||
|
|
||||||
|
not_null<Chat*> getChat(not_null<Dialogs::Row*> row);
|
||||||
|
void setActive(int active);
|
||||||
|
void updateUpon(const QPoint &pos);
|
||||||
|
|
||||||
|
void refresh();
|
||||||
|
|
||||||
|
float64 _columnSkip = 0.;
|
||||||
|
float64 _rowWidthReal = 0.;
|
||||||
|
int _rowsLeft = 0;
|
||||||
|
int _rowsTop = 0;
|
||||||
|
int _rowWidth = 0;
|
||||||
|
int _rowHeight = 0;
|
||||||
|
int _columnCount = 4;
|
||||||
|
int _active = -1;
|
||||||
|
int _upon = -1;
|
||||||
|
|
||||||
|
ShareBox::FilterCallback _filterCallback;
|
||||||
|
std::unique_ptr<Dialogs::IndexedList> _chatsIndexed;
|
||||||
|
QString _filter;
|
||||||
|
std::vector<Dialogs::Row*> _filtered;
|
||||||
|
|
||||||
|
std::map<not_null<PeerData*>, std::unique_ptr<Chat>> _dataMap;
|
||||||
|
base::flat_set<not_null<PeerData*>> _selected;
|
||||||
|
|
||||||
|
Fn<void(PeerData *peer, bool selected)> _peerSelectedChangedCallback;
|
||||||
|
|
||||||
|
bool _searching = false;
|
||||||
|
QString _lastQuery;
|
||||||
|
std::vector<PeerData*> _byUsernameFiltered;
|
||||||
|
std::vector<std::unique_ptr<Chat>> d_byUsernameFiltered;
|
||||||
|
|
||||||
|
rpl::event_stream<Ui::ScrollToRequest> _scrollToRequests;
|
||||||
|
rpl::event_stream<> _searchRequests;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
ShareBox::ShareBox(
|
||||||
|
QWidget*,
|
||||||
|
CopyCallback &©Callback,
|
||||||
|
SubmitCallback &&submitCallback,
|
||||||
|
FilterCallback &&filterCallback)
|
||||||
: _copyCallback(std::move(copyCallback))
|
: _copyCallback(std::move(copyCallback))
|
||||||
, _submitCallback(std::move(submitCallback))
|
, _submitCallback(std::move(submitCallback))
|
||||||
, _filterCallback(std::move(filterCallback))
|
, _filterCallback(std::move(filterCallback))
|
||||||
, _select(this, st::contactsMultiSelect, langFactory(lng_participant_filter))
|
, _select(
|
||||||
, _searchTimer(this) {
|
this,
|
||||||
|
st::contactsMultiSelect,
|
||||||
|
langFactory(lng_participant_filter))
|
||||||
|
, _comment(
|
||||||
|
this,
|
||||||
|
object_ptr<Ui::InputField>(
|
||||||
|
this,
|
||||||
|
st::shareComment,
|
||||||
|
Ui::InputField::Mode::MultiLine,
|
||||||
|
langFactory(lng_photos_comment)),
|
||||||
|
st::shareCommentPadding)
|
||||||
|
, _searchTimer([=] { searchByUsername(); }) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShareBox::prepareCommentField() {
|
||||||
|
using namespace rpl::mappers;
|
||||||
|
|
||||||
|
_comment->hide(anim::type::instant);
|
||||||
|
|
||||||
|
rpl::combine(
|
||||||
|
heightValue(),
|
||||||
|
_comment->heightValue(),
|
||||||
|
_1 - _2
|
||||||
|
) | rpl::start_with_next([=](int top) {
|
||||||
|
_comment->moveToLeft(0, top);
|
||||||
|
}, _comment->lifetime());
|
||||||
|
|
||||||
|
const auto field = _comment->entity();
|
||||||
|
|
||||||
|
connect(field, &Ui::InputField::submitted, [=] {
|
||||||
|
submit();
|
||||||
|
});
|
||||||
|
|
||||||
|
field->setInstantReplaces(Ui::InstantReplaces::Default());
|
||||||
|
field->setInstantReplacesEnabled(Global::ReplaceEmojiValue());
|
||||||
|
field->setMarkdownReplacesEnabled(rpl::single(true));
|
||||||
|
field->setEditLinkCallback(DefaultEditLinkCallback(field));
|
||||||
|
|
||||||
|
Ui::SendPendingMoveResizeEvents(_comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShareBox::prepare() {
|
void ShareBox::prepare() {
|
||||||
|
prepareCommentField();
|
||||||
|
|
||||||
_select->resizeToWidth(st::boxWideWidth);
|
_select->resizeToWidth(st::boxWideWidth);
|
||||||
Ui::SendPendingMoveResizeEvents(_select);
|
Ui::SendPendingMoveResizeEvents(_select);
|
||||||
|
|
||||||
setTitle(langFactory(lng_share_title));
|
setTitle(langFactory(lng_share_title));
|
||||||
|
|
||||||
_inner = setInnerWidget(object_ptr<Inner>(this, std::move(_filterCallback)), getTopScrollSkip());
|
_inner = setInnerWidget(
|
||||||
connect(_inner, SIGNAL(mustScrollTo(int,int)), this, SLOT(onMustScrollTo(int,int)));
|
object_ptr<Inner>(
|
||||||
|
this,
|
||||||
|
std::move(_filterCallback)),
|
||||||
|
getTopScrollSkip(),
|
||||||
|
getBottomScrollSkip());
|
||||||
|
|
||||||
createButtons();
|
createButtons();
|
||||||
|
|
||||||
setDimensions(st::boxWideWidth, st::boxMaxListHeight);
|
setDimensions(st::boxWideWidth, st::boxMaxListHeight);
|
||||||
|
|
||||||
_select->setQueryChangedCallback([this](const QString &query) { onFilterUpdate(query); });
|
_select->setQueryChangedCallback([=](const QString &query) {
|
||||||
_select->setItemRemovedCallback([this](uint64 itemId) {
|
onFilterUpdate(query);
|
||||||
if (auto peer = App::peerLoaded(itemId)) {
|
});
|
||||||
|
_select->setItemRemovedCallback([=](uint64 itemId) {
|
||||||
|
if (const auto peer = App::peerLoaded(itemId)) {
|
||||||
_inner->peerUnselected(peer);
|
_inner->peerUnselected(peer);
|
||||||
onSelectedChanged();
|
selectedChanged();
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
_select->setResizedCallback([this] { updateScrollSkips(); });
|
_select->setResizedCallback([=] { updateScrollSkips(); });
|
||||||
_select->setSubmittedCallback([this](Qt::KeyboardModifiers modifiers) {
|
_select->setSubmittedCallback([=](Qt::KeyboardModifiers modifiers) {
|
||||||
if (modifiers.testFlag(Qt::ControlModifier)
|
if (modifiers.testFlag(Qt::ControlModifier)
|
||||||
|| modifiers.testFlag(Qt::MetaModifier)) {
|
|| modifiers.testFlag(Qt::MetaModifier)) {
|
||||||
onSubmit();
|
submit();
|
||||||
} else {
|
} else {
|
||||||
_inner->onSelectActive();
|
_inner->selectActive();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
connect(_inner, SIGNAL(searchByUsername()), this, SLOT(onNeedSearchByUsername()));
|
_comment->heightValue(
|
||||||
_inner->setPeerSelectedChangedCallback([this](PeerData *peer, bool checked) {
|
) | rpl::start_with_next([=] {
|
||||||
onPeerSelectedChanged(peer, checked);
|
updateScrollSkips();
|
||||||
});
|
}, _comment->lifetime());
|
||||||
|
|
||||||
_searchTimer->setSingleShot(true);
|
_inner->searchRequests(
|
||||||
connect(_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchByUsername()));
|
) | rpl::start_with_next([=] {
|
||||||
|
needSearchByUsername();
|
||||||
|
}, _inner->lifetime());
|
||||||
|
|
||||||
|
_inner->scrollToRequests(
|
||||||
|
) | rpl::start_with_next([=](const Ui::ScrollToRequest &request) {
|
||||||
|
scrollTo(request);
|
||||||
|
}, _inner->lifetime());
|
||||||
|
|
||||||
|
_inner->setPeerSelectedChangedCallback([=](PeerData *peer, bool checked) {
|
||||||
|
innerSelectedChanged(peer, checked);
|
||||||
|
});
|
||||||
|
|
||||||
_select->raise();
|
_select->raise();
|
||||||
}
|
}
|
||||||
|
|
||||||
int ShareBox::getTopScrollSkip() const {
|
int ShareBox::getTopScrollSkip() const {
|
||||||
auto result = 0;
|
return _select->isHidden() ? 0 : _select->height();
|
||||||
if (!_select->isHidden()) {
|
}
|
||||||
result += _select->height();
|
|
||||||
}
|
int ShareBox::getBottomScrollSkip() const {
|
||||||
return result;
|
return _comment->isHidden() ? 0 : _comment->height();
|
||||||
|
}
|
||||||
|
|
||||||
|
int ShareBox::contentHeight() const {
|
||||||
|
return height() - getTopScrollSkip() - getBottomScrollSkip();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShareBox::updateScrollSkips() {
|
void ShareBox::updateScrollSkips() {
|
||||||
setInnerTopSkip(getTopScrollSkip(), true);
|
setInnerTopSkip(getTopScrollSkip(), true);
|
||||||
|
setInnerBottomSkip(getBottomScrollSkip());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShareBox::onSearchByUsername(bool searchCache) {
|
bool ShareBox::searchByUsername(bool searchCache) {
|
||||||
auto query = _select->getQuery();
|
auto query = _select->getQuery();
|
||||||
if (query.isEmpty()) {
|
if (query.isEmpty()) {
|
||||||
if (_peopleRequest) {
|
if (_peopleRequest) {
|
||||||
|
@ -124,9 +304,9 @@ bool ShareBox::onSearchByUsername(bool searchCache) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShareBox::onNeedSearchByUsername() {
|
void ShareBox::needSearchByUsername() {
|
||||||
if (!onSearchByUsername(true)) {
|
if (!searchByUsername(true)) {
|
||||||
_searchTimer->start(AutoSearchTimeout);
|
_searchTimer.callOnce(AutoSearchTimeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,7 +352,11 @@ bool ShareBox::peopleFailed(const RPCError &error, mtpRequestId requestId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShareBox::setInnerFocus() {
|
void ShareBox::setInnerFocus() {
|
||||||
_select->setInnerFocus();
|
if (_comment->isHidden()) {
|
||||||
|
_select->setInnerFocus();
|
||||||
|
} else {
|
||||||
|
_comment->entity()->setFocusFast();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShareBox::resizeEvent(QResizeEvent *e) {
|
void ShareBox::resizeEvent(QResizeEvent *e) {
|
||||||
|
@ -194,9 +378,9 @@ void ShareBox::keyPressEvent(QKeyEvent *e) {
|
||||||
} else if (e->key() == Qt::Key_Down) {
|
} else if (e->key() == Qt::Key_Down) {
|
||||||
_inner->activateSkipColumn(1);
|
_inner->activateSkipColumn(1);
|
||||||
} else if (e->key() == Qt::Key_PageUp) {
|
} else if (e->key() == Qt::Key_PageUp) {
|
||||||
_inner->activateSkipPage(height() - getTopScrollSkip(), -1);
|
_inner->activateSkipPage(contentHeight(), -1);
|
||||||
} else if (e->key() == Qt::Key_PageDown) {
|
} else if (e->key() == Qt::Key_PageDown) {
|
||||||
_inner->activateSkipPage(height() - getTopScrollSkip(), 1);
|
_inner->activateSkipPage(contentHeight(), 1);
|
||||||
} else {
|
} else {
|
||||||
BoxContent::keyPressEvent(e);
|
BoxContent::keyPressEvent(e);
|
||||||
}
|
}
|
||||||
|
@ -205,22 +389,14 @@ void ShareBox::keyPressEvent(QKeyEvent *e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShareBox::updateButtons() {
|
|
||||||
auto hasSelected = _inner->hasSelected();
|
|
||||||
if (_hasSelected != hasSelected) {
|
|
||||||
_hasSelected = hasSelected;
|
|
||||||
createButtons();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShareBox::createButtons() {
|
void ShareBox::createButtons() {
|
||||||
clearButtons();
|
clearButtons();
|
||||||
if (_hasSelected) {
|
if (_hasSelected) {
|
||||||
addButton(langFactory(lng_share_confirm), [this] { onSubmit(); });
|
addButton(langFactory(lng_share_confirm), [=] { submit(); });
|
||||||
} else if (_copyCallback) {
|
} else if (_copyCallback) {
|
||||||
addButton(langFactory(lng_share_copy_link), [this] { onCopyLink(); });
|
addButton(langFactory(lng_share_copy_link), [=] { copyLink(); });
|
||||||
}
|
}
|
||||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
addButton(langFactory(lng_cancel), [=] { closeBox(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShareBox::onFilterUpdate(const QString &query) {
|
void ShareBox::onFilterUpdate(const QString &query) {
|
||||||
|
@ -239,36 +415,44 @@ void ShareBox::addPeerToMultiSelect(PeerData *peer, bool skipAnimation) {
|
||||||
addItemWay);
|
addItemWay);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShareBox::onPeerSelectedChanged(PeerData *peer, bool checked) {
|
void ShareBox::innerSelectedChanged(PeerData *peer, bool checked) {
|
||||||
if (checked) {
|
if (checked) {
|
||||||
addPeerToMultiSelect(peer);
|
addPeerToMultiSelect(peer);
|
||||||
_select->clearQuery();
|
_select->clearQuery();
|
||||||
} else {
|
} else {
|
||||||
_select->removeItem(peer->id);
|
_select->removeItem(peer->id);
|
||||||
}
|
}
|
||||||
onSelectedChanged();
|
selectedChanged();
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShareBox::onSubmit() {
|
void ShareBox::submit() {
|
||||||
if (_submitCallback) {
|
if (_submitCallback) {
|
||||||
_submitCallback(_inner->selected());
|
_submitCallback(
|
||||||
|
_inner->selected(),
|
||||||
|
_comment->entity()->getTextWithAppliedMarkdown());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShareBox::onCopyLink() {
|
void ShareBox::copyLink() {
|
||||||
if (_copyCallback) {
|
if (_copyCallback) {
|
||||||
_copyCallback();
|
_copyCallback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShareBox::onSelectedChanged() {
|
void ShareBox::selectedChanged() {
|
||||||
updateButtons();
|
auto hasSelected = _inner->hasSelected();
|
||||||
|
if (_hasSelected != hasSelected) {
|
||||||
|
_hasSelected = hasSelected;
|
||||||
|
createButtons();
|
||||||
|
_comment->toggle(_hasSelected, anim::type::normal);
|
||||||
|
_comment->resizeToWidth(st::boxWideWidth);
|
||||||
|
}
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShareBox::onMustScrollTo(int top, int bottom) {
|
void ShareBox::scrollTo(Ui::ScrollToRequest request) {
|
||||||
onScrollToY(top, bottom);
|
onScrollToY(request.ymin, request.ymax);
|
||||||
//auto scrollTop = scrollArea()->scrollTop(), scrollBottom = scrollTop + scrollArea()->height();
|
//auto scrollTop = scrollArea()->scrollTop(), scrollBottom = scrollTop + scrollArea()->height();
|
||||||
//auto from = scrollTop, to = scrollTop;
|
//auto from = scrollTop, to = scrollTop;
|
||||||
//if (scrollTop > top) {
|
//if (scrollTop > top) {
|
||||||
|
@ -286,9 +470,14 @@ void ShareBox::scrollAnimationCallback() {
|
||||||
//scrollArea()->scrollToY(scrollTop);
|
//scrollArea()->scrollToY(scrollTop);
|
||||||
}
|
}
|
||||||
|
|
||||||
ShareBox::Inner::Inner(QWidget *parent, ShareBox::FilterCallback &&filterCallback) : TWidget(parent)
|
ShareBox::Inner::Inner(
|
||||||
|
QWidget *parent,
|
||||||
|
ShareBox::FilterCallback &&filterCallback)
|
||||||
|
: RpWidget(parent)
|
||||||
, _filterCallback(std::move(filterCallback))
|
, _filterCallback(std::move(filterCallback))
|
||||||
, _chatsIndexed(std::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Add)) {
|
, _chatsIndexed(
|
||||||
|
std::make_unique<Dialogs::IndexedList>(
|
||||||
|
Dialogs::SortMode::Add)) {
|
||||||
_rowsTop = st::shareRowsTop;
|
_rowsTop = st::shareRowsTop;
|
||||||
_rowHeight = st::shareRowHeight;
|
_rowHeight = st::shareRowHeight;
|
||||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||||
|
@ -325,7 +514,7 @@ ShareBox::Inner::Inner(QWidget *parent, ShareBox::FilterCallback &&filterCallbac
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShareBox::Inner::invalidateCache() {
|
void ShareBox::Inner::invalidateCache() {
|
||||||
for_const (auto data, _dataMap) {
|
for (const auto &[peer, data] : _dataMap) {
|
||||||
data->checkbox.invalidateCache();
|
data->checkbox.invalidateCache();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -377,9 +566,8 @@ void ShareBox::Inner::notifyPeerUpdated(const Notify::PeerUpdate &update) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShareBox::Inner::updateChat(not_null<PeerData*> peer) {
|
void ShareBox::Inner::updateChat(not_null<PeerData*> peer) {
|
||||||
auto i = _dataMap.find(peer);
|
if (const auto i = _dataMap.find(peer); i != end(_dataMap)) {
|
||||||
if (i != _dataMap.cend()) {
|
updateChatName(i->second.get(), peer);
|
||||||
updateChatName(i.value(), peer);
|
|
||||||
repaintChat(peer);
|
repaintChat(peer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -400,11 +588,17 @@ void ShareBox::Inner::repaintChatAtIndex(int index) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ShareBox::Inner::Chat *ShareBox::Inner::getChatAtIndex(int index) {
|
ShareBox::Inner::Chat *ShareBox::Inner::getChatAtIndex(int index) {
|
||||||
if (index < 0) return nullptr;
|
if (index < 0) {
|
||||||
auto row = ([this, index]() -> Dialogs::Row* {
|
return nullptr;
|
||||||
if (_filter.isEmpty()) return _chatsIndexed->rowAtY(index, 1);
|
}
|
||||||
return (index < _filtered.size()) ? _filtered[index] : nullptr;
|
const auto row = [=] {
|
||||||
})();
|
if (_filter.isEmpty()) {
|
||||||
|
return _chatsIndexed->rowAtY(index, 1);
|
||||||
|
}
|
||||||
|
return (index < _filtered.size())
|
||||||
|
? _filtered[index]
|
||||||
|
: nullptr;
|
||||||
|
}();
|
||||||
if (row) {
|
if (row) {
|
||||||
return static_cast<Chat*>(row->attached);
|
return static_cast<Chat*>(row->attached);
|
||||||
}
|
}
|
||||||
|
@ -412,7 +606,7 @@ ShareBox::Inner::Chat *ShareBox::Inner::getChatAtIndex(int index) {
|
||||||
if (!_filter.isEmpty()) {
|
if (!_filter.isEmpty()) {
|
||||||
index -= _filtered.size();
|
index -= _filtered.size();
|
||||||
if (index >= 0 && index < d_byUsernameFiltered.size()) {
|
if (index >= 0 && index < d_byUsernameFiltered.size()) {
|
||||||
return d_byUsernameFiltered[index];
|
return d_byUsernameFiltered[index].get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -442,7 +636,7 @@ int ShareBox::Inner::chatIndex(not_null<PeerData*> peer) const {
|
||||||
}
|
}
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
for (const auto row : d_byUsernameFiltered) {
|
for (const auto &row : d_byUsernameFiltered) {
|
||||||
if (row->peer == peer) {
|
if (row->peer == peer) {
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
@ -478,7 +672,7 @@ void ShareBox::Inner::loadProfilePhotos(int yFrom) {
|
||||||
(*i)->entry()->loadUserpic();
|
(*i)->entry()->loadUserpic();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!_filtered.isEmpty()) {
|
} else if (!_filtered.empty()) {
|
||||||
int from = yFrom / _rowHeight;
|
int from = yFrom / _rowHeight;
|
||||||
if (from < 0) from = 0;
|
if (from < 0) from = 0;
|
||||||
if (from < _filtered.size()) {
|
if (from < _filtered.size()) {
|
||||||
|
@ -492,23 +686,24 @@ void ShareBox::Inner::loadProfilePhotos(int yFrom) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ShareBox::Inner::Chat *ShareBox::Inner::getChat(Dialogs::Row *row) {
|
auto ShareBox::Inner::getChat(not_null<Dialogs::Row*> row)
|
||||||
|
-> not_null<Chat*> {
|
||||||
Expects(row->history() != nullptr);
|
Expects(row->history() != nullptr);
|
||||||
|
|
||||||
auto data = static_cast<Chat*>(row->attached);
|
if (const auto data = static_cast<Chat*>(row->attached)) {
|
||||||
if (!data) {
|
return data;
|
||||||
auto peer = row->history()->peer;
|
|
||||||
auto i = _dataMap.constFind(peer);
|
|
||||||
if (i == _dataMap.cend()) {
|
|
||||||
data = new Chat(peer, [this, peer] { repaintChat(peer); });
|
|
||||||
_dataMap.insert(peer, data);
|
|
||||||
updateChatName(data, peer);
|
|
||||||
} else {
|
|
||||||
data = i.value();
|
|
||||||
}
|
|
||||||
row->attached = data;
|
|
||||||
}
|
}
|
||||||
return data;
|
const auto peer = row->history()->peer;
|
||||||
|
if (const auto i = _dataMap.find(peer); i != end(_dataMap)) {
|
||||||
|
row->attached = i->second.get();
|
||||||
|
return i->second.get();
|
||||||
|
}
|
||||||
|
const auto [i, ok] = _dataMap.emplace(
|
||||||
|
peer,
|
||||||
|
std::make_unique<Chat>(peer, [=] { repaintChat(peer); }));
|
||||||
|
updateChatName(i->second.get(), peer);
|
||||||
|
row->attached = i->second.get();
|
||||||
|
return i->second.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShareBox::Inner::setActive(int active) {
|
void ShareBox::Inner::setActive(int active) {
|
||||||
|
@ -525,7 +720,7 @@ void ShareBox::Inner::setActive(int active) {
|
||||||
changeNameFg(_active, 0., 1.);
|
changeNameFg(_active, 0., 1.);
|
||||||
}
|
}
|
||||||
auto y = (_active < _columnCount) ? 0 : (_rowsTop + ((_active / _columnCount) * _rowHeight));
|
auto y = (_active < _columnCount) ? 0 : (_rowsTop + ((_active / _columnCount) * _rowHeight));
|
||||||
emit mustScrollTo(y, y + _rowHeight);
|
_scrollToRequests.fire({ y, y + _rowHeight });
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShareBox::Inner::paintChat(
|
void ShareBox::Inner::paintChat(
|
||||||
|
@ -587,7 +782,7 @@ void ShareBox::Inner::paintEvent(QPaintEvent *e) {
|
||||||
style::al_center);
|
style::al_center);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (_filtered.isEmpty()
|
if (_filtered.empty()
|
||||||
&& _byUsernameFiltered.empty()
|
&& _byUsernameFiltered.empty()
|
||||||
&& !_searching) {
|
&& !_searching) {
|
||||||
p.setFont(st::noContactsFont);
|
p.setFont(st::noContactsFont);
|
||||||
|
@ -616,7 +811,11 @@ void ShareBox::Inner::paintEvent(QPaintEvent *e) {
|
||||||
if (indexFrom >= d_byUsernameFiltered.size()) {
|
if (indexFrom >= d_byUsernameFiltered.size()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
paintChat(p, ms, d_byUsernameFiltered[indexFrom], filteredSize + indexFrom);
|
paintChat(
|
||||||
|
p,
|
||||||
|
ms,
|
||||||
|
d_byUsernameFiltered[indexFrom].get(),
|
||||||
|
filteredSize + indexFrom);
|
||||||
++indexFrom;
|
++indexFrom;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -659,7 +858,7 @@ void ShareBox::Inner::mousePressEvent(QMouseEvent *e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShareBox::Inner::onSelectActive() {
|
void ShareBox::Inner::selectActive() {
|
||||||
changeCheckState(getChatAtIndex(_active > 0 ? _active : 0));
|
changeCheckState(getChatAtIndex(_active > 0 ? _active : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -693,12 +892,16 @@ void ShareBox::Inner::changeCheckState(Chat *chat) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShareBox::Inner::peerUnselected(not_null<PeerData*> peer) {
|
void ShareBox::Inner::peerUnselected(not_null<PeerData*> peer) {
|
||||||
if (auto chat = _dataMap.value(peer, nullptr)) {
|
if (const auto i = _dataMap.find(peer); i != end(_dataMap)) {
|
||||||
changePeerCheckState(chat, false, ChangeStateWay::SkipCallback);
|
changePeerCheckState(
|
||||||
|
i->second.get(),
|
||||||
|
false,
|
||||||
|
ChangeStateWay::SkipCallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShareBox::Inner::setPeerSelectedChangedCallback(Fn<void(PeerData *peer, bool selected)> callback) {
|
void ShareBox::Inner::setPeerSelectedChangedCallback(
|
||||||
|
Fn<void(PeerData *peer, bool selected)> callback) {
|
||||||
_peerSelectedChangedCallback = std::move(callback);
|
_peerSelectedChangedCallback = std::move(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -732,9 +935,6 @@ void ShareBox::Inner::updateFilter(QString filter) {
|
||||||
_filter = filter;
|
_filter = filter;
|
||||||
|
|
||||||
_byUsernameFiltered.clear();
|
_byUsernameFiltered.clear();
|
||||||
for (int i = 0, l = d_byUsernameFiltered.size(); i < l; ++i) {
|
|
||||||
delete d_byUsernameFiltered[i];
|
|
||||||
}
|
|
||||||
d_byUsernameFiltered.clear();
|
d_byUsernameFiltered.clear();
|
||||||
|
|
||||||
if (_filter.isEmpty()) {
|
if (_filter.isEmpty()) {
|
||||||
|
@ -782,7 +982,7 @@ void ShareBox::Inner::updateFilter(QString filter) {
|
||||||
refresh();
|
refresh();
|
||||||
|
|
||||||
_searching = true;
|
_searching = true;
|
||||||
emit searchByUsername();
|
_searchRequests.fire({});
|
||||||
}
|
}
|
||||||
setActive(-1);
|
setActive(-1);
|
||||||
update();
|
update();
|
||||||
|
@ -790,6 +990,14 @@ void ShareBox::Inner::updateFilter(QString filter) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpl::producer<Ui::ScrollToRequest> ShareBox::Inner::scrollToRequests() const {
|
||||||
|
return _scrollToRequests.events();
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<> ShareBox::Inner::searchRequests() const {
|
||||||
|
return _searchRequests.events();
|
||||||
|
}
|
||||||
|
|
||||||
void ShareBox::Inner::peopleReceived(
|
void ShareBox::Inner::peopleReceived(
|
||||||
const QString &query,
|
const QString &query,
|
||||||
const QVector<MTPPeer> &my,
|
const QVector<MTPPeer> &my,
|
||||||
|
@ -802,8 +1010,8 @@ void ShareBox::Inner::peopleReceived(
|
||||||
_byUsernameFiltered.reserve(already + my.size() + people.size());
|
_byUsernameFiltered.reserve(already + my.size() + people.size());
|
||||||
d_byUsernameFiltered.reserve(already + my.size() + people.size());
|
d_byUsernameFiltered.reserve(already + my.size() + people.size());
|
||||||
const auto feedList = [&](const QVector<MTPPeer> &list) {
|
const auto feedList = [&](const QVector<MTPPeer> &list) {
|
||||||
for (const auto &mtpPeer : list) {
|
for (const auto &data : list) {
|
||||||
if (const auto peer = App::peerLoaded(peerFromMTP(mtpPeer))) {
|
if (const auto peer = App::peerLoaded(peerFromMTP(data))) {
|
||||||
const auto history = App::historyLoaded(peer);
|
const auto history = App::historyLoaded(peer);
|
||||||
if (!_filterCallback(peer)) {
|
if (!_filterCallback(peer)) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -812,10 +1020,11 @@ void ShareBox::Inner::peopleReceived(
|
||||||
} else if (base::contains(_byUsernameFiltered, peer)) {
|
} else if (base::contains(_byUsernameFiltered, peer)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto chat = new Chat(peer, [=] { repaintChat(peer); });
|
|
||||||
updateChatName(chat, peer);
|
|
||||||
_byUsernameFiltered.push_back(peer);
|
_byUsernameFiltered.push_back(peer);
|
||||||
d_byUsernameFiltered.push_back(chat);
|
d_byUsernameFiltered.push_back(std::make_unique<Chat>(
|
||||||
|
peer,
|
||||||
|
[=] { repaintChat(peer); }));
|
||||||
|
updateChatName(d_byUsernameFiltered.back().get(), peer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -837,18 +1046,12 @@ void ShareBox::Inner::refresh() {
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
ShareBox::Inner::~Inner() {
|
|
||||||
for_const (auto chat, _dataMap) {
|
|
||||||
delete chat;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QVector<PeerData*> ShareBox::Inner::selected() const {
|
QVector<PeerData*> ShareBox::Inner::selected() const {
|
||||||
QVector<PeerData*> result;
|
auto result = QVector<PeerData*>();
|
||||||
result.reserve(_dataMap.size());
|
result.reserve(_dataMap.size());
|
||||||
for_const (auto chat, _dataMap) {
|
for (const auto &[peer, chat] : _dataMap) {
|
||||||
if (chat->checkbox.checked()) {
|
if (chat->checkbox.checked()) {
|
||||||
result.push_back(chat->peer);
|
result.push_back(peer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
#include "boxes/abstract_box.h"
|
#include "boxes/abstract_box.h"
|
||||||
#include "base/observer.h"
|
#include "base/observer.h"
|
||||||
|
#include "base/timer.h"
|
||||||
#include "ui/effects/round_checkbox.h"
|
#include "ui/effects/round_checkbox.h"
|
||||||
|
|
||||||
namespace Dialogs {
|
namespace Dialogs {
|
||||||
|
@ -22,19 +23,25 @@ struct PeerUpdate;
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class MultiSelect;
|
class MultiSelect;
|
||||||
|
class InputField;
|
||||||
|
struct ScrollToRequest;
|
||||||
|
template <typename Widget>
|
||||||
|
class SlideWrap;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
QString AppendShareGameScoreUrl(const QString &url, const FullMsgId &fullId);
|
QString AppendShareGameScoreUrl(const QString &url, const FullMsgId &fullId);
|
||||||
void ShareGameScoreByHash(const QString &hash);
|
void ShareGameScoreByHash(const QString &hash);
|
||||||
|
|
||||||
class ShareBox : public BoxContent, public RPCSender {
|
class ShareBox : public BoxContent, public RPCSender {
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using CopyCallback = Fn<void()>;
|
using CopyCallback = Fn<void()>;
|
||||||
using SubmitCallback = Fn<void(const QVector<PeerData*> &)>;
|
using SubmitCallback = Fn<void(QVector<PeerData*>&&, TextWithTags&&)>;
|
||||||
using FilterCallback = Fn<bool(PeerData*)>;
|
using FilterCallback = Fn<bool(PeerData*)>;
|
||||||
ShareBox(QWidget*, CopyCallback &©Callback, SubmitCallback &&submitCallback, FilterCallback &&filterCallback);
|
ShareBox(
|
||||||
|
QWidget*,
|
||||||
|
CopyCallback &©Callback,
|
||||||
|
SubmitCallback &&submitCallback,
|
||||||
|
FilterCallback &&filterCallback);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void prepare() override;
|
void prepare() override;
|
||||||
|
@ -43,27 +50,26 @@ protected:
|
||||||
void resizeEvent(QResizeEvent *e) override;
|
void resizeEvent(QResizeEvent *e) override;
|
||||||
void keyPressEvent(QKeyEvent *e) override;
|
void keyPressEvent(QKeyEvent *e) override;
|
||||||
|
|
||||||
private slots:
|
|
||||||
bool onSearchByUsername(bool searchCache = false);
|
|
||||||
void onNeedSearchByUsername();
|
|
||||||
|
|
||||||
void onSubmit();
|
|
||||||
void onCopyLink();
|
|
||||||
|
|
||||||
void onMustScrollTo(int top, int bottom);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void prepareCommentField();
|
||||||
void scrollAnimationCallback();
|
void scrollAnimationCallback();
|
||||||
|
|
||||||
|
void submit();
|
||||||
|
void copyLink();
|
||||||
|
bool searchByUsername(bool useCache = false);
|
||||||
|
|
||||||
|
void scrollTo(Ui::ScrollToRequest request);
|
||||||
|
void needSearchByUsername();
|
||||||
void onFilterUpdate(const QString &query);
|
void onFilterUpdate(const QString &query);
|
||||||
void onSelectedChanged();
|
void selectedChanged();
|
||||||
void updateButtons();
|
|
||||||
void createButtons();
|
void createButtons();
|
||||||
int getTopScrollSkip() const;
|
int getTopScrollSkip() const;
|
||||||
|
int getBottomScrollSkip() const;
|
||||||
|
int contentHeight() const;
|
||||||
void updateScrollSkips();
|
void updateScrollSkips();
|
||||||
|
|
||||||
void addPeerToMultiSelect(PeerData *peer, bool skipAnimation = false);
|
void addPeerToMultiSelect(PeerData *peer, bool skipAnimation = false);
|
||||||
void onPeerSelectedChanged(PeerData *peer, bool checked);
|
void innerSelectedChanged(PeerData *peer, bool checked);
|
||||||
|
|
||||||
void peopleReceived(
|
void peopleReceived(
|
||||||
const MTPcontacts_Found &result,
|
const MTPcontacts_Found &result,
|
||||||
|
@ -75,13 +81,14 @@ private:
|
||||||
FilterCallback _filterCallback;
|
FilterCallback _filterCallback;
|
||||||
|
|
||||||
object_ptr<Ui::MultiSelect> _select;
|
object_ptr<Ui::MultiSelect> _select;
|
||||||
|
object_ptr<Ui::SlideWrap<Ui::InputField>> _comment;
|
||||||
|
|
||||||
class Inner;
|
class Inner;
|
||||||
QPointer<Inner> _inner;
|
QPointer<Inner> _inner;
|
||||||
|
|
||||||
bool _hasSelected = false;
|
bool _hasSelected = false;
|
||||||
|
|
||||||
object_ptr<QTimer> _searchTimer;
|
base::Timer _searchTimer;
|
||||||
QString _peopleQuery;
|
QString _peopleQuery;
|
||||||
bool _peopleFull = false;
|
bool _peopleFull = false;
|
||||||
mtpRequestId _peopleRequest = 0;
|
mtpRequestId _peopleRequest = 0;
|
||||||
|
@ -95,119 +102,3 @@ private:
|
||||||
Animation _scrollAnimation;
|
Animation _scrollAnimation;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// This class is hold in header because it requires Qt preprocessing.
|
|
||||||
class ShareBox::Inner : public TWidget, public RPCSender, private base::Subscriber {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
Inner(QWidget *parent, ShareBox::FilterCallback &&filterCallback);
|
|
||||||
|
|
||||||
void setPeerSelectedChangedCallback(Fn<void(PeerData *peer, bool selected)> callback);
|
|
||||||
void peerUnselected(not_null<PeerData*> peer);
|
|
||||||
|
|
||||||
QVector<PeerData*> selected() const;
|
|
||||||
bool hasSelected() const;
|
|
||||||
|
|
||||||
void peopleReceived(
|
|
||||||
const QString &query,
|
|
||||||
const QVector<MTPPeer> &my,
|
|
||||||
const QVector<MTPPeer> &people);
|
|
||||||
|
|
||||||
void activateSkipRow(int direction);
|
|
||||||
void activateSkipColumn(int direction);
|
|
||||||
void activateSkipPage(int pageHeight, int direction);
|
|
||||||
void updateFilter(QString filter = QString());
|
|
||||||
|
|
||||||
~Inner();
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void onSelectActive();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void mustScrollTo(int ymin, int ymax);
|
|
||||||
void searchByUsername();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void visibleTopBottomUpdated(
|
|
||||||
int visibleTop,
|
|
||||||
int visibleBottom) override;
|
|
||||||
|
|
||||||
void paintEvent(QPaintEvent *e) override;
|
|
||||||
void enterEventHook(QEvent *e) override;
|
|
||||||
void leaveEventHook(QEvent *e) override;
|
|
||||||
void mouseMoveEvent(QMouseEvent *e) override;
|
|
||||||
void mousePressEvent(QMouseEvent *e) override;
|
|
||||||
void resizeEvent(QResizeEvent *e) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Observed notifications.
|
|
||||||
void notifyPeerUpdated(const Notify::PeerUpdate &update);
|
|
||||||
void invalidateCache();
|
|
||||||
|
|
||||||
int displayedChatsCount() const;
|
|
||||||
|
|
||||||
struct Chat {
|
|
||||||
Chat(PeerData *peer, Fn<void()> updateCallback);
|
|
||||||
|
|
||||||
PeerData *peer;
|
|
||||||
Ui::RoundImageCheckbox checkbox;
|
|
||||||
Text name;
|
|
||||||
Animation nameActive;
|
|
||||||
};
|
|
||||||
void paintChat(Painter &p, TimeMs ms, not_null<Chat*> chat, int index);
|
|
||||||
void updateChat(not_null<PeerData*> peer);
|
|
||||||
void updateChatName(not_null<Chat*> chat, not_null<PeerData*> peer);
|
|
||||||
void repaintChat(not_null<PeerData*> peer);
|
|
||||||
int chatIndex(not_null<PeerData*> peer) const;
|
|
||||||
void repaintChatAtIndex(int index);
|
|
||||||
Chat *getChatAtIndex(int index);
|
|
||||||
|
|
||||||
void loadProfilePhotos(int yFrom);
|
|
||||||
void changeCheckState(Chat *chat);
|
|
||||||
enum class ChangeStateWay {
|
|
||||||
Default,
|
|
||||||
SkipCallback,
|
|
||||||
};
|
|
||||||
void changePeerCheckState(
|
|
||||||
not_null<Chat*> chat,
|
|
||||||
bool checked,
|
|
||||||
ChangeStateWay useCallback = ChangeStateWay::Default);
|
|
||||||
|
|
||||||
Chat *getChat(Dialogs::Row *row);
|
|
||||||
void setActive(int active);
|
|
||||||
void updateUpon(const QPoint &pos);
|
|
||||||
|
|
||||||
void refresh();
|
|
||||||
|
|
||||||
float64 _columnSkip = 0.;
|
|
||||||
float64 _rowWidthReal = 0.;
|
|
||||||
int _rowsLeft = 0;
|
|
||||||
int _rowsTop = 0;
|
|
||||||
int _rowWidth = 0;
|
|
||||||
int _rowHeight = 0;
|
|
||||||
int _columnCount = 4;
|
|
||||||
int _active = -1;
|
|
||||||
int _upon = -1;
|
|
||||||
|
|
||||||
ShareBox::FilterCallback _filterCallback;
|
|
||||||
std::unique_ptr<Dialogs::IndexedList> _chatsIndexed;
|
|
||||||
QString _filter;
|
|
||||||
using FilteredDialogs = QVector<Dialogs::Row*>;
|
|
||||||
FilteredDialogs _filtered;
|
|
||||||
|
|
||||||
using DataMap = QMap<PeerData*, Chat*>;
|
|
||||||
DataMap _dataMap;
|
|
||||||
using SelectedChats = OrderedSet<PeerData*>;
|
|
||||||
SelectedChats _selected;
|
|
||||||
|
|
||||||
Fn<void(PeerData *peer, bool selected)> _peerSelectedChangedCallback;
|
|
||||||
|
|
||||||
ChatData *data(Dialogs::Row *row);
|
|
||||||
|
|
||||||
bool _searching = false;
|
|
||||||
QString _lastQuery;
|
|
||||||
std::vector<PeerData*> _byUsernameFiltered;
|
|
||||||
std::vector<Chat*> d_byUsernameFiltered;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
|
@ -279,7 +279,6 @@ Fn<bool(
|
||||||
QString text,
|
QString text,
|
||||||
QString link,
|
QString link,
|
||||||
EditLinkAction action)> DefaultEditLinkCallback(
|
EditLinkAction action)> DefaultEditLinkCallback(
|
||||||
not_null<Window::Controller*> controller,
|
|
||||||
not_null<Ui::InputField*> field) {
|
not_null<Ui::InputField*> field) {
|
||||||
const auto weak = make_weak(field);
|
const auto weak = make_weak(field);
|
||||||
return [=](
|
return [=](
|
||||||
|
@ -318,8 +317,7 @@ void InitMessageField(
|
||||||
field->setInstantReplaces(Ui::InstantReplaces::Default());
|
field->setInstantReplaces(Ui::InstantReplaces::Default());
|
||||||
field->setInstantReplacesEnabled(Global::ReplaceEmojiValue());
|
field->setInstantReplacesEnabled(Global::ReplaceEmojiValue());
|
||||||
field->setMarkdownReplacesEnabled(rpl::single(true));
|
field->setMarkdownReplacesEnabled(rpl::single(true));
|
||||||
field->setEditLinkCallback(
|
field->setEditLinkCallback(DefaultEditLinkCallback(field));
|
||||||
DefaultEditLinkCallback(controller, field));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasSendText(not_null<const Ui::InputField*> field) {
|
bool HasSendText(not_null<const Ui::InputField*> field) {
|
||||||
|
|
|
@ -32,7 +32,6 @@ Fn<bool(
|
||||||
QString text,
|
QString text,
|
||||||
QString link,
|
QString link,
|
||||||
Ui::InputField::EditLinkAction action)> DefaultEditLinkCallback(
|
Ui::InputField::EditLinkAction action)> DefaultEditLinkCallback(
|
||||||
not_null<Window::Controller*> controller,
|
|
||||||
not_null<Ui::InputField*> field);
|
not_null<Ui::InputField*> field);
|
||||||
void InitMessageField(
|
void InitMessageField(
|
||||||
not_null<Window::Controller*> controller,
|
not_null<Window::Controller*> controller,
|
||||||
|
|
|
@ -123,7 +123,9 @@ void FastShareMessage(not_null<HistoryItem*> item) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
auto submitCallback = [data, isGroup](const QVector<PeerData*> &result) {
|
auto submitCallback = [=](
|
||||||
|
QVector<PeerData*> &&result,
|
||||||
|
TextWithTags &&comment) {
|
||||||
if (!data->requests.empty()) {
|
if (!data->requests.empty()) {
|
||||||
return; // Share clicked already.
|
return; // Share clicked already.
|
||||||
}
|
}
|
||||||
|
@ -187,6 +189,13 @@ void FastShareMessage(not_null<HistoryItem*> item) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto history = App::history(peer);
|
||||||
|
if (!comment.text.isEmpty()) {
|
||||||
|
auto message = ApiWrap::MessageToSend(history);
|
||||||
|
message.textWithTags = comment;
|
||||||
|
message.clearDraft = false;
|
||||||
|
Auth().api().sendMessage(std::move(message));
|
||||||
|
}
|
||||||
auto request = MTPmessages_ForwardMessages(
|
auto request = MTPmessages_ForwardMessages(
|
||||||
MTP_flags(sendFlags),
|
MTP_flags(sendFlags),
|
||||||
data->peer->input,
|
data->peer->input,
|
||||||
|
@ -194,8 +203,14 @@ void FastShareMessage(not_null<HistoryItem*> item) {
|
||||||
MTP_vector<MTPlong>(generateRandom()),
|
MTP_vector<MTPlong>(generateRandom()),
|
||||||
peer->input);
|
peer->input);
|
||||||
auto callback = doneCallback;
|
auto callback = doneCallback;
|
||||||
auto requestId = MTP::send(request, rpcDone(std::move(callback)));
|
history->sendRequestId = MTP::send(
|
||||||
data->requests.insert(requestId);
|
request,
|
||||||
|
rpcDone(base::duplicate(doneCallback)),
|
||||||
|
nullptr,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
history->sendRequestId);
|
||||||
|
data->requests.insert(history->sendRequestId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue