mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2026-08-12 06:33:59 +00:00
[poll-create] Added poll answer link entry and preview.
This commit is contained in:
@@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "boxes/create_poll_box.h"
|
||||
|
||||
#include "poll/poll_link_thumbnail.h"
|
||||
#include "poll/poll_media_upload.h"
|
||||
#include "base/call_delayed.h"
|
||||
#include "base/qt/qt_key_modifiers.h"
|
||||
@@ -36,7 +37,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "data/data_photo.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_user.h"
|
||||
#include "data/data_web_page.h"
|
||||
#include "data/stickers/data_custom_emoji.h"
|
||||
#include "history/view/controls/history_view_webpage_processor.h"
|
||||
#include "history/view/media/menu/history_view_poll_menu.h"
|
||||
#include "history/view/history_view_schedule_box.h"
|
||||
#include "info/channel_statistics/boosts/giveaway/select_countries_box.h"
|
||||
@@ -75,6 +78,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/widgets/fields/input_field.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/boxes/choose_date_time.h"
|
||||
#include "ui/layers/generic_box.h"
|
||||
#include "ui/text/format_values.h"
|
||||
#include "ui/widgets/popup_menu.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
@@ -340,6 +344,51 @@ void FocusAtEnd(not_null<Ui::InputField*> field) {
|
||||
field->ensureCursorVisible();
|
||||
}
|
||||
|
||||
void AddPollOptionLinkBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
const QString &initial,
|
||||
Fn<void(QString)> callback) {
|
||||
box->setTitle(tr::lng_polls_create_option_link_title());
|
||||
|
||||
const auto content = box->verticalLayout();
|
||||
content->add(
|
||||
object_ptr<Ui::FlatLabel>(
|
||||
content,
|
||||
tr::lng_polls_create_option_link_description(),
|
||||
st::defaultFlatLabel),
|
||||
st::boxRowPadding);
|
||||
Ui::AddSkip(content);
|
||||
Ui::AddSkip(content);
|
||||
|
||||
const auto field = content->add(
|
||||
object_ptr<Ui::InputField>(
|
||||
content,
|
||||
st::createPollLinkUrlField,
|
||||
Ui::InputField::Mode::SingleLine,
|
||||
tr::lng_polls_create_option_link_placeholder(),
|
||||
initial),
|
||||
st::boxRowPadding);
|
||||
|
||||
const auto submit = [=] {
|
||||
const auto url = field->getLastText().trimmed();
|
||||
if (url.isEmpty()) {
|
||||
field->showError();
|
||||
return;
|
||||
}
|
||||
const auto weak = base::make_weak(box);
|
||||
callback(url);
|
||||
if (weak) {
|
||||
box->closeBox();
|
||||
}
|
||||
};
|
||||
field->submits(
|
||||
) | rpl::on_next(submit, field->lifetime());
|
||||
|
||||
box->addButton(tr::lng_box_done(), submit);
|
||||
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
||||
box->setFocusCallback([=] { field->setFocusFast(); });
|
||||
}
|
||||
|
||||
[[nodiscard]] QStringList ParsePastedList(const QString &text) {
|
||||
auto list = QStringView(text).split('\n');
|
||||
for (auto i = list.begin(); i != list.end();) {
|
||||
@@ -1570,6 +1619,9 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
||||
= std::make_shared<PollMediaState>();
|
||||
std::shared_ptr<PollMediaState> solutionMedia
|
||||
= std::make_shared<PollMediaState>();
|
||||
std::shared_ptr<HistoryView::Controls::WebpageResolver>
|
||||
webpageResolver;
|
||||
base::flat_map<PollMediaState*, rpl::lifetime> webPageLifetimes;
|
||||
std::weak_ptr<PollMediaState> stickerTarget;
|
||||
base::flat_map<FullMsgId, UploadContext> uploads;
|
||||
base::unique_qptr<Ui::PopupMenu> mediaMenu;
|
||||
@@ -1582,6 +1634,8 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
||||
};
|
||||
const auto state = lifetime().make_state<State>();
|
||||
state->prepareQueue = std::make_unique<TaskQueue>();
|
||||
state->webpageResolver = std::make_shared<
|
||||
HistoryView::Controls::WebpageResolver>(&_controller->session());
|
||||
|
||||
auto result = object_ptr<Ui::VerticalLayout>(this);
|
||||
const auto container = result.data();
|
||||
@@ -2461,6 +2515,89 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
||||
FileDialog::AllFilesFilter(),
|
||||
callback);
|
||||
};
|
||||
const auto applyResolvedWebPage = [=](
|
||||
std::shared_ptr<PollMediaState> media,
|
||||
not_null<WebPageData*> page) {
|
||||
auto pollMedia = PollMedia();
|
||||
pollMedia.webpage = page;
|
||||
pollMedia.url = page->url.isEmpty() ? media->media.url : page->url;
|
||||
auto thumbnail = page->photo
|
||||
? Ui::MakePhotoThumbnailCenterCrop(page->photo, FullMsgId())
|
||||
: Poll::MakeLinkThumbnail();
|
||||
const auto rounded = (page->photo != nullptr);
|
||||
setMedia(media, pollMedia, std::move(thumbnail), rounded);
|
||||
};
|
||||
const auto subscribeToWebPageUpdates = [=](
|
||||
std::shared_ptr<PollMediaState> media,
|
||||
not_null<WebPageData*> page) {
|
||||
const auto raw = media.get();
|
||||
const auto weak = std::weak_ptr<PollMediaState>(media);
|
||||
_controller->session().data().webPageUpdates(
|
||||
) | rpl::filter([=](not_null<WebPageData*> updated) {
|
||||
const auto locked = weak.lock();
|
||||
return locked
|
||||
&& (updated == page)
|
||||
&& (locked->media.webpage == page);
|
||||
}) | rpl::on_next([=] {
|
||||
if (const auto locked = weak.lock()) {
|
||||
applyResolvedWebPage(locked, page);
|
||||
}
|
||||
}, state->webPageLifetimes[raw]);
|
||||
};
|
||||
const auto resolveLink = [=](
|
||||
std::shared_ptr<PollMediaState> media,
|
||||
QString url) {
|
||||
const auto raw = media.get();
|
||||
const auto weak = std::weak_ptr<PollMediaState>(media);
|
||||
state->webPageLifetimes[raw].destroy();
|
||||
const auto token = media->token;
|
||||
const auto apply = [=](const QString &resolvedUrl) {
|
||||
const auto locked = weak.lock();
|
||||
if (!locked || locked->token != token || resolvedUrl != url) {
|
||||
return;
|
||||
}
|
||||
const auto cached = state->webpageResolver->lookup(url);
|
||||
if (!cached || !*cached) {
|
||||
return;
|
||||
}
|
||||
const auto page = *cached;
|
||||
applyResolvedWebPage(locked, page);
|
||||
subscribeToWebPageUpdates(locked, page);
|
||||
};
|
||||
if (const auto cached = state->webpageResolver->lookup(url)) {
|
||||
if (*cached) {
|
||||
applyResolvedWebPage(media, *cached);
|
||||
subscribeToWebPageUpdates(media, *cached);
|
||||
}
|
||||
return;
|
||||
}
|
||||
state->webPageLifetimes[raw]
|
||||
= state->webpageResolver->resolved(
|
||||
) | rpl::filter([=](const QString &resolvedUrl) {
|
||||
const auto locked = weak.lock();
|
||||
return locked
|
||||
&& (resolvedUrl == url)
|
||||
&& (locked->token == token);
|
||||
}) | rpl::take(1) | rpl::on_next(apply);
|
||||
state->webpageResolver->request(url);
|
||||
};
|
||||
const auto chooseLink = [=](std::shared_ptr<PollMediaState> media) {
|
||||
const auto initial = media->media.url;
|
||||
const auto callback = crl::guard(this, [=](QString url) {
|
||||
auto pollMedia = PollMedia();
|
||||
pollMedia.url = url;
|
||||
setMedia(
|
||||
media,
|
||||
pollMedia,
|
||||
Poll::MakeLinkThumbnail(),
|
||||
false);
|
||||
resolveLink(media, url);
|
||||
});
|
||||
_controller->show(Box(
|
||||
AddPollOptionLinkBox,
|
||||
initial,
|
||||
callback));
|
||||
};
|
||||
const auto clearMedia = [=](std::shared_ptr<PollMediaState> media) {
|
||||
auto toCancel = std::vector<FullMsgId>();
|
||||
for (auto i = state->uploads.begin(); i != state->uploads.end();) {
|
||||
@@ -2474,6 +2611,7 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
||||
for (const auto &id : toCancel) {
|
||||
_controller->session().uploader().cancel(id);
|
||||
}
|
||||
state->webPageLifetimes.remove(media.get());
|
||||
setMedia(media, PollMedia(), nullptr, false);
|
||||
};
|
||||
const auto chooseLocation = [=](
|
||||
@@ -2580,6 +2718,10 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
||||
[=] { showStickerPanel(button, media); },
|
||||
&st::menuIconStickers);
|
||||
}
|
||||
state->mediaMenu->addAction(
|
||||
tr::lng_polls_create_option_link(tr::now),
|
||||
[=] { chooseLink(media); },
|
||||
&st::menuIconLink);
|
||||
if (media->media || media->uploading) {
|
||||
state->mediaMenu->addAction(
|
||||
tr::lng_box_remove(tr::now),
|
||||
|
||||
Reference in New Issue
Block a user