Skip to content

Commit 0d2ea71

Browse files
23rdjohn-preston
authored andcommitted
[img-editor] Added photo button row to stickers list widget.
1 parent 5591f1e commit 0d2ea71

8 files changed

Lines changed: 138 additions & 3 deletions

File tree

Lines changed: 4 additions & 0 deletions
Loading

Telegram/SourceFiles/chat_helpers/chat_helpers.style

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ EmojiPan {
153153
searchBackIconTop: pixels;
154154
searchBackTextLeft: pixels;
155155
searchBackTextTop: pixels;
156+
photoButtonIcon: icon;
156157
colorAll: IconButton;
157158
colorAllLabel: FlatLabel;
158159
removeSet: IconButton;
@@ -629,6 +630,12 @@ stickerIconMove: 400;
629630
stickerPreviewDuration: 150;
630631
stickerPreviewMin: 0.1;
631632
stickerPanFirstAfterShortcutsSkip: 4px;
633+
stickersPhotoRowPadding: margins(0px, 12px, 0px, 12px);
634+
stickersPhotoButtonHeight: 36px;
635+
stickersPhotoButtonRadius: 8px;
636+
stickersPhotoButtonPadding: margins(6px, 0px, 12px, 0px);
637+
stickersPhotoButtonIconSkip: 4px;
638+
stickersPhotoButtonFont: font(21px bold);
632639
mediaPreviewPhotoSkip: 48px;
633640

634641
emojiPanColorAll: IconButton(stickerPanRemoveSet) {
@@ -822,6 +829,7 @@ defaultEmojiPan: EmojiPan {
822829
searchBackIconTop: 6px;
823830
searchBackTextLeft: 40px;
824831
searchBackTextTop: 10px;
832+
photoButtonIcon: icon {{ "photo_editor/camera-24x24", windowFg }};
825833
colorAll: emojiPanColorAll;
826834
colorAllLabel: emojiPanColorAllLabel;
827835
removeSet: stickerPanRemoveSet;

Telegram/SourceFiles/chat_helpers/compose/compose_features.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ struct ComposeFeatures {
2222
bool collectibleStatus : 1 = false;
2323
bool stickersSettings : 1 = true;
2424
bool openStickerSets : 1 = true;
25+
bool photoButton : 1 = false;
2526
bool autocompleteHashtags : 1 = true;
2627
bool autocompleteMentions : 1 = true;
2728
bool autocompleteCommands : 1 = true;

Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp

Lines changed: 96 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,9 @@ StickersListWidget::StickersListWidget(
240240
, _megagroupSetAbout(st::columnMinimalWidthThird
241241
- st::emojiScroll.width
242242
- st().headerLeft)
243+
, _photoButtonBg(st::stickersPhotoButtonRadius, st().overBg)
244+
, _photoButtonText(tr::lng_attach_photo(tr::now).toUpper())
245+
, _photoButtonTextWidth(st::stickersPhotoButtonFont->width(_photoButtonText))
243246
, _addText(tr::lng_stickers_featured_add(tr::now))
244247
, _addWidth(st::stickersTrendingAdd.style.font->width(_addText))
245248
, _installedText(tr::lng_stickers_featured_installed(tr::now))
@@ -317,6 +320,10 @@ rpl::producer<FileChosen> StickersListWidget::chosen() const {
317320
return _chosen.events();
318321
}
319322

323+
rpl::producer<> StickersListWidget::photoRequests() const {
324+
return _photoRequests.events();
325+
}
326+
320327
rpl::producer<> StickersListWidget::scrollUpdated() const {
321328
return _scrollUpdated.events();
322329
}
@@ -502,7 +509,7 @@ template <typename Callback>
502509
bool StickersListWidget::enumerateSections(Callback callback) const {
503510
auto info = SectionInfo();
504511
info.top = _search ? _search->height() : 0;
505-
info.top += searchShortcutsHeight();
512+
info.top += photoRowHeight() + searchShortcutsHeight();
506513
const auto &sets = shownSets();
507514
for (auto i = 0; i != sets.size(); ++i) {
508515
auto &set = sets[i];
@@ -969,7 +976,69 @@ void StickersListWidget::startSearchSwapAnimation(
969976
}
970977

971978
int StickersListWidget::searchShortcutsTop() const {
972-
return _search ? _search->height() : 0;
979+
return (_search ? _search->height() : 0) + photoRowHeight();
980+
}
981+
982+
int StickersListWidget::photoRowHeight() const {
983+
if (!_features.photoButton || _isMasks || _section == Section::Search) {
984+
return 0;
985+
}
986+
const auto &padding = st::stickersPhotoRowPadding;
987+
return padding.top() + st::stickersPhotoButtonHeight + padding.bottom();
988+
}
989+
990+
QRect StickersListWidget::photoButtonRect() const {
991+
const auto &padding = st::stickersPhotoButtonPadding;
992+
const auto &icon = st().photoButtonIcon;
993+
const auto buttonWidth = padding.left()
994+
+ icon.width()
995+
+ st::stickersPhotoButtonIconSkip
996+
+ _photoButtonTextWidth
997+
+ padding.right();
998+
const auto top = (_search ? _search->height() : 0)
999+
+ st::stickersPhotoRowPadding.top();
1000+
return QRect(
1001+
(width() - buttonWidth) / 2,
1002+
top,
1003+
buttonWidth,
1004+
st::stickersPhotoButtonHeight);
1005+
}
1006+
1007+
void StickersListWidget::paintPhotoButton(Painter &p, QRect clip) {
1008+
if (!photoRowHeight()) {
1009+
return;
1010+
}
1011+
const auto rect = photoButtonRect();
1012+
if (!rect.intersects(clip)) {
1013+
return;
1014+
}
1015+
_photoButtonBg.paint(p, myrtlrect(rect));
1016+
if (_photoButtonRipple) {
1017+
_photoButtonRipple->paint(p, myrtlrect(rect).x(), rect.y(), width());
1018+
if (_photoButtonRipple->empty()) {
1019+
_photoButtonRipple.reset();
1020+
}
1021+
}
1022+
const auto &padding = st::stickersPhotoButtonPadding;
1023+
const auto &icon = st().photoButtonIcon;
1024+
icon.paint(
1025+
p,
1026+
rect.x() + padding.left(),
1027+
rect.y() + (rect.height() - icon.height()) / 2,
1028+
width());
1029+
const auto &font = st::stickersPhotoButtonFont;
1030+
const auto textLeft = rect.x()
1031+
+ padding.left()
1032+
+ icon.width()
1033+
+ st::stickersPhotoButtonIconSkip;
1034+
p.setFont(font);
1035+
p.setPen(st().textFg);
1036+
p.drawTextLeft(
1037+
textLeft,
1038+
rect.y() + (rect.height() - font->height) / 2,
1039+
width(),
1040+
_photoButtonText,
1041+
_photoButtonTextWidth);
9731042
}
9741043

9751044
int StickersListWidget::searchShortcutsHeight() const {
@@ -1555,6 +1624,7 @@ void StickersListWidget::paintStickers(Painter &p, QRect clip) {
15551624
_paintAsPremium = session().premium();
15561625
_pathGradient->startFrame(0, width(), width() / 2);
15571626
paintSearchShortcuts(p, clip);
1627+
paintPhotoButton(p, clip);
15581628

15591629
auto &sets = shownSets();
15601630
const auto selectedSticker = std::get_if<OverSticker>(&_selected);
@@ -2412,6 +2482,10 @@ void StickersListWidget::setPressed(OverState newPressed) {
24122482
if (_megagroupSetButtonRipple) {
24132483
_megagroupSetButtonRipple->lastStop();
24142484
}
2485+
} else if (std::get_if<OverPhotoButton>(&_pressed)) {
2486+
if (_photoButtonRipple) {
2487+
_photoButtonRipple->lastStop();
2488+
}
24152489
}
24162490
_pressed = newPressed;
24172491
if (auto button = std::get_if<OverButton>(&_pressed)) {
@@ -2445,6 +2519,18 @@ void StickersListWidget::setPressed(OverState newPressed) {
24452519
}
24462520
_megagroupSetButtonRipple->add(mapFromGlobal(QCursor::pos())
24472521
- myrtlrect(megagroupSetButtonRectFinal()).topLeft());
2522+
} else if (std::get_if<OverPhotoButton>(&_pressed)) {
2523+
if (!_photoButtonRipple) {
2524+
auto mask = Ui::RippleAnimation::RoundRectMask(
2525+
photoButtonRect().size(),
2526+
st::stickersPhotoButtonRadius);
2527+
_photoButtonRipple = std::make_unique<Ui::RippleAnimation>(
2528+
st().searchPackRipple,
2529+
std::move(mask),
2530+
[this] { rtlupdate(photoButtonRect()); });
2531+
}
2532+
_photoButtonRipple->add(mapFromGlobal(QCursor::pos())
2533+
- myrtlrect(photoButtonRect()).topLeft());
24482534
}
24492535
}
24502536

@@ -2779,6 +2865,9 @@ void StickersListWidget::mouseReleaseEvent(QMouseEvent *e) {
27792865
if (std::get_if<OverSearchBack>(&pressed)) {
27802866
backToSearchResults();
27812867
return;
2868+
} else if (std::get_if<OverPhotoButton>(&pressed)) {
2869+
_photoRequests.fire({});
2870+
return;
27822871
} else if (auto shortcut = std::get_if<OverSearchShortcut>(&pressed)) {
27832872
toggleSearchShortcut(shortcut->index);
27842873
return;
@@ -3556,6 +3645,9 @@ void StickersListWidget::updateSelected() {
35563645
}
35573646
setSelected(newSelected);
35583647
return;
3648+
} else if (photoRowHeight() && myrtlrect(photoButtonRect()).contains(p)) {
3649+
setSelected(OverPhotoButton{});
3650+
return;
35593651
}
35603652
const auto &sets = shownSets();
35613653
auto sx = (rtl() ? width() - p.x() : p.x()) - stickersLeft();
@@ -3667,6 +3759,8 @@ void StickersListWidget::setSelected(OverState newSelected) {
36673759
rtlupdate(searchBackRect());
36683760
} else if (std::get_if<OverGroupAdd>(&_selected)) {
36693761
rtlupdate(megagroupSetButtonRectFinal());
3762+
} else if (std::get_if<OverPhotoButton>(&_selected)) {
3763+
rtlupdate(photoButtonRect());
36703764
}
36713765
};
36723766
updateSelected();

Telegram/SourceFiles/chat_helpers/stickers_list_widget.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ class StickersListWidget final : public TabbedSelector::Inner {
104104
StickersListDescriptor &&descriptor);
105105

106106
rpl::producer<FileChosen> chosen() const;
107+
[[nodiscard]] rpl::producer<> photoRequests() const;
107108
rpl::producer<> scrollUpdated() const;
108109
rpl::producer<TabbedSelector::Action> choosingUpdated() const;
109110

@@ -232,14 +233,23 @@ class StickersListWidget final : public TabbedSelector::Inner {
232233
return !(*this == other);
233234
}
234235
};
236+
struct OverPhotoButton {
237+
inline bool operator==(OverPhotoButton other) const {
238+
return true;
239+
}
240+
inline bool operator!=(OverPhotoButton other) const {
241+
return !(*this == other);
242+
}
243+
};
235244
using OverState = std::variant<
236245
v::null_t,
237246
OverSticker,
238247
OverSet,
239248
OverButton,
240249
OverSearchShortcut,
241250
OverSearchBack,
242-
OverGroupAdd>;
251+
OverGroupAdd,
252+
OverPhotoButton>;
243253

244254
struct SectionInfo {
245255
int section = 0;
@@ -310,6 +320,9 @@ class StickersListWidget final : public TabbedSelector::Inner {
310320
void readVisibleFeatured(int visibleTop, int visibleBottom);
311321

312322
void paintStickers(Painter &p, QRect clip);
323+
void paintPhotoButton(Painter &p, QRect clip);
324+
[[nodiscard]] int photoRowHeight() const;
325+
[[nodiscard]] QRect photoButtonRect() const;
313326
void paintMegagroupEmptySet(Painter &p, int y, bool buttonSelected);
314327
void paintSticker(
315328
Painter &p,
@@ -494,6 +507,11 @@ class StickersListWidget final : public TabbedSelector::Inner {
494507
QRect _megagroupSetButtonRect;
495508
std::unique_ptr<Ui::RippleAnimation> _megagroupSetButtonRipple;
496509

510+
Ui::RoundRect _photoButtonBg;
511+
QString _photoButtonText;
512+
int _photoButtonTextWidth = 0;
513+
std::unique_ptr<Ui::RippleAnimation> _photoButtonRipple;
514+
497515
QString _addText;
498516
int _addWidth;
499517
QString _installedText;
@@ -532,6 +550,7 @@ class StickersListWidget final : public TabbedSelector::Inner {
532550
bool _searchLoading = false;
533551

534552
rpl::event_stream<FileChosen> _chosen;
553+
rpl::event_stream<> _photoRequests;
535554
rpl::event_stream<> _scrollUpdated;
536555
rpl::event_stream<TabbedSelector::Action> _choosingUpdated;
537556

Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,10 @@ auto TabbedSelector::inlineResultChosen() const
746746
return hasGifsTab() ? gifs()->inlineResultChosen() : nullptr;
747747
}
748748

749+
rpl::producer<> TabbedSelector::photoRequests() const {
750+
return hasStickersTab() ? stickers()->photoRequests() : rpl::never<>();
751+
}
752+
749753
auto TabbedSelector::choosingStickerUpdated() const
750754
-> rpl::producer<TabbedSelector::Action>{
751755
return hasStickersTab()

Telegram/SourceFiles/chat_helpers/tabbed_selector.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ class TabbedSelector : public Ui::RpWidget {
148148
[[nodiscard]] rpl::producer<FileChosen> fileChosen() const;
149149
[[nodiscard]] rpl::producer<PhotoChosen> photoChosen() const;
150150
[[nodiscard]] rpl::producer<InlineChosen> inlineResultChosen() const;
151+
[[nodiscard]] rpl::producer<> photoRequests() const;
151152

152153
[[nodiscard]] rpl::producer<> cancelled() const;
153154
[[nodiscard]] rpl::producer<> checkForHide() const;

Telegram/SourceFiles/media/view/media_view.style

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,10 @@ storiesEmojiPan: EmojiPan(defaultEmojiPan) {
661661
categoriesBgOver: storiesComposeBgOver;
662662
fadeLeft: icon {{ "fade_horizontal-flip_horizontal", storiesComposeBg }};
663663
fadeRight: icon {{ "fade_horizontal", storiesComposeBg }};
664+
photoButtonIcon: icon {{
665+
"photo_editor/camera-24x24",
666+
storiesComposeWhiteText
667+
}};
664668
menu: storiesPopupMenuWithIcons;
665669
menuAttention: storiesMenuWithIconsAttention;
666670
expandedSeparator: mediaviewWideMenuSeparator;

0 commit comments

Comments
 (0)