mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2026-07-25 06:54:43 +00:00
[poll-create] Added document file preview overlay.
This commit is contained in:
@@ -2251,6 +2251,13 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
||||
},
|
||||
remove);
|
||||
return;
|
||||
} else if (document) {
|
||||
HistoryView::ShowPollDocumentPreview(
|
||||
_controller,
|
||||
document,
|
||||
[=] { chooseDocument(media); },
|
||||
remove);
|
||||
return;
|
||||
}
|
||||
state->mediaMenu = base::make_unique_q<Ui::PopupMenu>(
|
||||
button,
|
||||
|
||||
@@ -35,6 +35,24 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
namespace HistoryView {
|
||||
namespace {
|
||||
|
||||
void SetupOverlayHideOnEscape(
|
||||
not_null<Ui::AbstractButton*> clickable,
|
||||
Fn<void()> hideAll) {
|
||||
clickable->setClickedCallback(hideAll);
|
||||
base::install_event_filter(QCoreApplication::instance(), [=](
|
||||
not_null<QEvent*> e) {
|
||||
if (e->type() == QEvent::KeyPress
|
||||
&& clickable->window()->isActiveWindow()) {
|
||||
const auto k = static_cast<QKeyEvent*>(e.get());
|
||||
if (k->key() == Qt::Key_Escape) {
|
||||
hideAll();
|
||||
return base::EventFilterResult::Cancel;
|
||||
}
|
||||
}
|
||||
return base::EventFilterResult::Continue;
|
||||
}, clickable->lifetime());
|
||||
}
|
||||
|
||||
struct PreviewOverlayState {
|
||||
base::unique_qptr<Window::MediaPreviewWidget> mediaPreview;
|
||||
base::unique_qptr<Ui::AbstractButton> clickable;
|
||||
@@ -80,19 +98,7 @@ template <typename MediaData>
|
||||
st::defaultToggle.duration,
|
||||
[=] { state->clear(); });
|
||||
};
|
||||
state->clickable->setClickedCallback(hideAll);
|
||||
base::install_event_filter(QCoreApplication::instance(), [=](
|
||||
not_null<QEvent*> e) {
|
||||
if (e->type() == QEvent::KeyPress
|
||||
&& state->clickable->window()->isActiveWindow()) {
|
||||
const auto k = static_cast<QKeyEvent*>(e.get());
|
||||
if (k->key() == Qt::Key_Escape) {
|
||||
hideAll();
|
||||
return base::EventFilterResult::Cancel;
|
||||
}
|
||||
}
|
||||
return base::EventFilterResult::Continue;
|
||||
}, state->clickable->lifetime());
|
||||
SetupOverlayHideOnEscape(state->clickable.get(), hideAll);
|
||||
state->mediaPreview->showPreview(origin, media);
|
||||
state->clickable->show();
|
||||
const auto clickableRaw = state->clickable.get();
|
||||
@@ -284,4 +290,74 @@ bool ShowReactionPreview(
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShowWidgetPreview(
|
||||
not_null<Window::SessionController*> controller,
|
||||
Fn<void(not_null<Ui::RpWidget*>)> setupContent,
|
||||
Fn<void(not_null<Ui::DropdownMenu*>)> fillMenu) {
|
||||
struct State {
|
||||
base::unique_qptr<Ui::RpWidget> preview;
|
||||
base::unique_qptr<Ui::AbstractButton> clickable;
|
||||
base::unique_qptr<Ui::DropdownMenu> menu;
|
||||
};
|
||||
const auto state = std::make_shared<State>();
|
||||
const auto mainwidget = controller->widget()->bodyWidget();
|
||||
|
||||
state->preview = base::make_unique_q<Ui::RpWidget>(mainwidget);
|
||||
const auto previewRaw = state->preview.get();
|
||||
setupContent(previewRaw);
|
||||
previewRaw->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
|
||||
state->clickable = base::make_unique_q<Ui::AbstractButton>(mainwidget);
|
||||
state->clickable->paintOn([=](QPainter &p) {
|
||||
p.fillRect(state->clickable->rect(), st::stickerPreviewBg);
|
||||
});
|
||||
|
||||
const auto hideAll = [=] {
|
||||
state->clickable->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
if (state->menu) {
|
||||
state->menu->hideAnimated();
|
||||
}
|
||||
base::call_delayed(
|
||||
st::defaultToggle.duration,
|
||||
[s = state] {
|
||||
s->preview.reset();
|
||||
s->menu.reset();
|
||||
s->clickable.reset();
|
||||
});
|
||||
};
|
||||
SetupOverlayHideOnEscape(state->clickable.get(), hideAll);
|
||||
|
||||
state->menu = base::make_unique_q<Ui::DropdownMenu>(
|
||||
mainwidget,
|
||||
st::dropdownMenuWithIcons);
|
||||
state->menu->setAutoHiding(false);
|
||||
state->menu->setHiddenCallback(
|
||||
crl::guard(state->clickable.get(), hideAll));
|
||||
fillMenu(state->menu.get());
|
||||
|
||||
const auto menuRaw = state->menu.get();
|
||||
state->clickable->show();
|
||||
previewRaw->show();
|
||||
|
||||
const auto fullW = previewRaw->width();
|
||||
const auto fullH = previewRaw->height();
|
||||
|
||||
mainwidget->sizeValue() | rpl::on_next([=](QSize size) {
|
||||
state->clickable->setGeometry(Rect(size));
|
||||
state->clickable->raise();
|
||||
|
||||
const auto gap = st::defaultMenu.itemPadding.top();
|
||||
const auto totalH = fullH + gap + menuRaw->height();
|
||||
const auto previewY = (size.height() - totalH) / 2;
|
||||
previewRaw->move((size.width() - fullW) / 2, previewY);
|
||||
previewRaw->raise();
|
||||
|
||||
menuRaw->move(
|
||||
(size.width() - menuRaw->width()) / 2,
|
||||
previewY + fullH + gap);
|
||||
menuRaw->showAnimated(Ui::PanelAnimation::Origin::TopLeft);
|
||||
menuRaw->raise();
|
||||
}, previewRaw->lifetime());
|
||||
}
|
||||
|
||||
} // namespace HistoryView
|
||||
|
||||
@@ -12,6 +12,7 @@ class PhotoData;
|
||||
|
||||
namespace Ui {
|
||||
class DropdownMenu;
|
||||
class RpWidget;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Data {
|
||||
@@ -36,6 +37,11 @@ bool ShowPhotoPreview(
|
||||
not_null<PhotoData*> photo,
|
||||
Fn<void(not_null<Ui::DropdownMenu*>)> fillMenu = nullptr);
|
||||
|
||||
void ShowWidgetPreview(
|
||||
not_null<Window::SessionController*> controller,
|
||||
Fn<void(not_null<Ui::RpWidget*>)> setupContent,
|
||||
Fn<void(not_null<Ui::DropdownMenu*>)> fillMenu);
|
||||
|
||||
bool ShowReactionPreview(
|
||||
not_null<Window::SessionController*> controller,
|
||||
FullMsgId origin,
|
||||
|
||||
@@ -23,17 +23,23 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "history/view/history_view_group_call_bar.h"
|
||||
#include "history/view/history_view_reaction_preview.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "layout/layout_document_generic_preview.h"
|
||||
#include "main/main_session.h"
|
||||
#include "mainwidget.h"
|
||||
#include "storage/localimageloader.h"
|
||||
#include "storage/storage_media_prepare.h"
|
||||
#include "ui/chat/attach/attach_prepare.h"
|
||||
#include "ui/painter.h"
|
||||
#include "ui/rect.h"
|
||||
#include "ui/text/format_values.h"
|
||||
#include "ui/widgets/dropdown_menu.h"
|
||||
#include "ui/widgets/menu/menu_action.h"
|
||||
#include "ui/widgets/shadow.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_chat.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_media_view.h"
|
||||
#include "styles/style_menu_icons.h"
|
||||
#include "styles/style_widgets.h"
|
||||
|
||||
@@ -287,6 +293,124 @@ void ShowPollPhotoPreview(
|
||||
});
|
||||
}
|
||||
|
||||
void ShowPollDocumentPreview(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<DocumentData*> document,
|
||||
Fn<void()> replace,
|
||||
Fn<void()> remove) {
|
||||
const auto docGeneric = Layout::DocumentGenericPreview::Create(
|
||||
document);
|
||||
const auto docIcon = docGeneric.icon();
|
||||
const auto docIconColor = docGeneric.color;
|
||||
const auto docExt = [&] {
|
||||
auto ext = docGeneric.ext;
|
||||
const auto maxW = st::mediaviewFileIconSize
|
||||
- st::mediaviewFileExtPadding * 2;
|
||||
if (st::mediaviewFileExtFont->width(ext) > maxW) {
|
||||
ext = st::mediaviewFileExtFont->elided(ext, maxW, Qt::ElideMiddle);
|
||||
}
|
||||
return ext;
|
||||
}();
|
||||
|
||||
const auto maxTextW = st::mediaviewFileSize.width()
|
||||
- st::mediaviewFileIconSize
|
||||
- st::mediaviewFilePadding * 3;
|
||||
const auto docName = [&] {
|
||||
auto name = document->filename().isEmpty()
|
||||
? tr::lng_mediaview_doc_image(tr::now)
|
||||
: document->filename();
|
||||
if (st::mediaviewFileNameFont->width(name) > maxTextW) {
|
||||
name = st::mediaviewFileNameFont->elided(name, maxTextW, Qt::ElideMiddle);
|
||||
}
|
||||
return name;
|
||||
}();
|
||||
const auto docSize = [&] {
|
||||
auto text = Ui::FormatSizeText(document->size);
|
||||
if (st::mediaviewFont->width(text) > maxTextW) {
|
||||
text = st::mediaviewFont->elided(text, maxTextW);
|
||||
}
|
||||
return text;
|
||||
}();
|
||||
|
||||
ShowWidgetPreview(controller, [=](not_null<Ui::RpWidget*> preview) {
|
||||
const auto shadowExtend = st::boxRoundShadow.extend;
|
||||
const auto fullW = st::mediaviewFileSize.width()
|
||||
+ rect::m::sum::h(shadowExtend);
|
||||
const auto fullH = st::mediaviewFileSize.height()
|
||||
+ rect::m::sum::v(shadowExtend);
|
||||
preview->resize(fullW, fullH);
|
||||
preview->paintRequest() | rpl::on_next([=] {
|
||||
auto p = Painter(preview);
|
||||
const auto outer = preview->rect() - shadowExtend;
|
||||
|
||||
Ui::Shadow::paint(
|
||||
p,
|
||||
outer,
|
||||
preview->width(),
|
||||
st::boxRoundShadow);
|
||||
{
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(st::windowBg);
|
||||
p.drawRoundedRect(outer, st::boxRadius, st::boxRadius);
|
||||
}
|
||||
|
||||
const auto padding = st::mediaviewFilePadding;
|
||||
const auto iconSize = st::mediaviewFileIconSize;
|
||||
const auto iconRect = QRect(
|
||||
outer.x() + padding,
|
||||
outer.y() + padding,
|
||||
iconSize,
|
||||
iconSize);
|
||||
|
||||
p.fillRect(iconRect, docIconColor);
|
||||
if (docIcon) {
|
||||
docIcon->paint(
|
||||
p,
|
||||
iconRect.x() + (iconRect.width() - docIcon->width()),
|
||||
iconRect.y(),
|
||||
preview->width());
|
||||
}
|
||||
if (!docExt.isEmpty()) {
|
||||
p.setPen(st::activeButtonFg);
|
||||
p.setFont(st::mediaviewFileExtFont);
|
||||
const auto extW = st::mediaviewFileExtFont->width(docExt);
|
||||
p.drawText(
|
||||
iconRect.x() + (iconRect.width() - extW) / 2,
|
||||
iconRect.y()
|
||||
+ st::mediaviewFileExtTop
|
||||
+ st::mediaviewFileExtFont->ascent,
|
||||
docExt);
|
||||
}
|
||||
|
||||
const auto textX = outer.x() + 2 * padding + iconSize;
|
||||
p.setPen(st::windowFg);
|
||||
p.setFont(st::mediaviewFileNameFont);
|
||||
p.drawText(
|
||||
textX,
|
||||
outer.y() + padding
|
||||
+ st::mediaviewFileNameTop
|
||||
+ st::mediaviewFileNameFont->ascent,
|
||||
docName);
|
||||
|
||||
p.setPen(st::windowSubTextFg);
|
||||
p.setFont(st::mediaviewFont);
|
||||
p.drawText(
|
||||
textX,
|
||||
outer.y() + padding
|
||||
+ st::mediaviewFileSizeTop
|
||||
+ st::mediaviewFont->ascent,
|
||||
docSize);
|
||||
}, preview->lifetime());
|
||||
}, [=](not_null<Ui::DropdownMenu*> menu) {
|
||||
menu->addAction(
|
||||
tr::lng_attach_replace(tr::now),
|
||||
replace,
|
||||
&st::menuIconReplace);
|
||||
AddRemoveAction(menu, remove);
|
||||
});
|
||||
}
|
||||
|
||||
void EditPollPhoto(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<PhotoData*> photo,
|
||||
|
||||
@@ -43,6 +43,12 @@ void ShowPollPhotoPreview(
|
||||
Fn<void()> edit,
|
||||
Fn<void()> remove);
|
||||
|
||||
void ShowPollDocumentPreview(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<DocumentData*> document,
|
||||
Fn<void()> replace,
|
||||
Fn<void()> remove);
|
||||
|
||||
void EditPollPhoto(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<PhotoData*> photo,
|
||||
|
||||
Reference in New Issue
Block a user