Finish improved stories reply area theming.
|
@ -348,6 +348,7 @@ PRIVATE
|
|||
calls/calls_video_bubble.h
|
||||
calls/calls_video_incoming.cpp
|
||||
calls/calls_video_incoming.h
|
||||
chat_helpers/compose/compose_features.h
|
||||
chat_helpers/compose/compose_show.cpp
|
||||
chat_helpers/compose/compose_show.h
|
||||
chat_helpers/bot_command.cpp
|
||||
|
|
Before Width: | Height: | Size: 470 B |
Before Width: | Height: | Size: 899 B |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 255 B |
Before Width: | Height: | Size: 312 B |
Before Width: | Height: | Size: 494 B |
Before Width: | Height: | Size: 527 B |
Before Width: | Height: | Size: 1,007 B |
Before Width: | Height: | Size: 1.4 KiB |
|
@ -606,6 +606,7 @@ void StickerSetBox::updateButtons() {
|
|||
const auto session = &_show->session();
|
||||
auto box = ChatHelpers::MakeConfirmRemoveSetBox(
|
||||
session,
|
||||
st::boxLabel,
|
||||
_inner->setId());
|
||||
if (box) {
|
||||
_show->showBox(std::move(box));
|
||||
|
|
|
@ -63,7 +63,7 @@ ShowButton::ShowButton(not_null<Ui::RpWidget*> parent)
|
|||
_button.sizeValue(
|
||||
) | rpl::start_with_next([=](const QSize &s) {
|
||||
resize(
|
||||
s.width() + st::emojiSuggestionsFadeRight.width(),
|
||||
s.width() + st::defaultEmojiSuggestions.fadeRight.width(),
|
||||
s.height());
|
||||
_button.moveToRight(0, 0);
|
||||
}, lifetime());
|
||||
|
@ -74,7 +74,7 @@ void ShowButton::paintEvent(QPaintEvent *e) {
|
|||
auto p = QPainter(this);
|
||||
const auto clip = e->rect();
|
||||
|
||||
const auto &icon = st::emojiSuggestionsFadeRight;
|
||||
const auto &icon = st::defaultEmojiSuggestions.fadeRight;
|
||||
const auto fade = QRect(0, 0, icon.width(), height());
|
||||
if (fade.intersects(clip)) {
|
||||
icon.fill(p, fade);
|
||||
|
|
|
@ -10,6 +10,7 @@ using "ui/basic.style";
|
|||
using "boxes/boxes.style";
|
||||
using "ui/layers/layers.style";
|
||||
using "ui/widgets/widgets.style";
|
||||
using "ui/menu_icons.style";
|
||||
|
||||
GroupCallUserpics {
|
||||
size: pixels;
|
||||
|
@ -36,9 +37,50 @@ TabbedSearch {
|
|||
height: pixels;
|
||||
}
|
||||
|
||||
ComposeIcons {
|
||||
settings: icon;
|
||||
|
||||
recent: icon;
|
||||
recentActive: icon;
|
||||
people: icon;
|
||||
peopleActive: icon;
|
||||
nature: icon;
|
||||
natureActive: icon;
|
||||
food: icon;
|
||||
foodActive: icon;
|
||||
activity: icon;
|
||||
activityActive: icon;
|
||||
travel: icon;
|
||||
travelActive: icon;
|
||||
objects: icon;
|
||||
objectsActive: icon;
|
||||
symbols: icon;
|
||||
symbolsActive: icon;
|
||||
|
||||
menuFave: icon;
|
||||
menuUnfave: icon;
|
||||
menuStickerSet: icon;
|
||||
menuRecentRemove: icon;
|
||||
menuGifAdd: icon;
|
||||
menuGifRemove: icon;
|
||||
menuMute: icon;
|
||||
menuSchedule: icon;
|
||||
menuWhenOnline: icon;
|
||||
}
|
||||
|
||||
EmojiSuggestions {
|
||||
dropdown: InnerDropdown;
|
||||
bg: color;
|
||||
overBg: color;
|
||||
textFg: color;
|
||||
fadeLeft: icon;
|
||||
fadeRight: icon;
|
||||
}
|
||||
|
||||
EmojiPan {
|
||||
margin: margins;
|
||||
padding: margins;
|
||||
showAnimation: PanelAnimation;
|
||||
desiredSize: pixels;
|
||||
verticalSizeSub: pixels;
|
||||
header: pixels;
|
||||
|
@ -51,8 +93,12 @@ EmojiPan {
|
|||
iconWidth: pixels;
|
||||
iconArea: pixels;
|
||||
bg: color;
|
||||
headerFg: color;
|
||||
trendingHeaderFg: color;
|
||||
trendingSubheaderFg: color;
|
||||
trendingUnreadFg: color;
|
||||
trendingInstalled: icon;
|
||||
overBg: color;
|
||||
expandBg: color;
|
||||
pathBg: color;
|
||||
pathFg: color;
|
||||
textFg: color;
|
||||
|
@ -60,9 +106,14 @@ EmojiPan {
|
|||
categoriesBgOver: color;
|
||||
fadeLeft: icon;
|
||||
fadeRight: icon;
|
||||
menu: PopupMenu;
|
||||
tabs: SettingsSlider;
|
||||
search: TabbedSearch;
|
||||
searchMargin: margins;
|
||||
removeSet: IconButton;
|
||||
boxLabel: FlatLabel;
|
||||
icons: ComposeIcons;
|
||||
autocompleteBottomSkip: pixels;
|
||||
}
|
||||
|
||||
MessageBar {
|
||||
|
@ -96,6 +147,7 @@ ComposeControls {
|
|||
send: SendButton;
|
||||
attach: IconButton;
|
||||
emoji: EmojiButton;
|
||||
suggestions: EmojiSuggestions;
|
||||
tabbed: EmojiPan;
|
||||
}
|
||||
|
||||
|
@ -191,12 +243,6 @@ stickersScroll: ScrollArea(boxScroll) {
|
|||
stickersRowDisabledOpacity: 0.4;
|
||||
stickersRowDuration: 200;
|
||||
|
||||
stickersSettings: icon {{ "emoji/emoji_settings", emojiIconFg }};
|
||||
stickersTrending: icon {{ "emoji/stickers_add", emojiIconFg }};
|
||||
stickersTrendingUnread: icon {
|
||||
{ "emoji/stickers_add_unread", emojiIconFg },
|
||||
{ "emoji/stickers_add_dot", dialogsUnreadBg }
|
||||
};
|
||||
emojiStatusDefault: icon {{ "emoji/stickers_premium", emojiIconFg }};
|
||||
|
||||
filtersRemove: IconButton(stickersRemove) {
|
||||
|
@ -210,22 +256,6 @@ emojiTabs: SettingsSlider(defaultTabsSlider) {
|
|||
barTop: 40px;
|
||||
labelTop: 12px;
|
||||
}
|
||||
emojiRecent: icon {{ "emoji/emoji_recent", emojiIconFg }};
|
||||
emojiRecentActive: icon {{ "emoji/emoji_recent", emojiSubIconFgActive }};
|
||||
emojiPeople: icon {{ "emoji/emoji_smile", emojiIconFg }};
|
||||
emojiPeopleActive: icon {{ "emoji/emoji_smile", emojiSubIconFgActive }};
|
||||
emojiNature: icon {{ "emoji/emoji_nature", emojiIconFg }};
|
||||
emojiNatureActive: icon {{ "emoji/emoji_nature", emojiSubIconFgActive }};
|
||||
emojiFood: icon {{ "emoji/emoji_food", emojiIconFg }};
|
||||
emojiFoodActive: icon {{ "emoji/emoji_food", emojiSubIconFgActive }};
|
||||
emojiActivity: icon {{ "emoji/emoji_activities", emojiIconFg }};
|
||||
emojiActivityActive: icon {{ "emoji/emoji_activities", emojiSubIconFgActive }};
|
||||
emojiTravel: icon {{ "emoji/emoji_travel", emojiIconFg }};
|
||||
emojiTravelActive: icon {{ "emoji/emoji_travel", emojiSubIconFgActive }};
|
||||
emojiObjects: icon {{ "emoji/emoji_objects", emojiIconFg }};
|
||||
emojiObjectsActive: icon {{ "emoji/emoji_objects", emojiSubIconFgActive }};
|
||||
emojiSymbols: icon {{ "emoji/emoji_love", emojiIconFg }};
|
||||
emojiSymbolsActive: icon {{ "emoji/emoji_love", emojiSubIconFgActive }};
|
||||
|
||||
emojiCategoryIconTop: 6px;
|
||||
emojiPanAnimation: PanelAnimation(defaultPanelAnimation) {
|
||||
|
@ -297,40 +327,6 @@ defaultTabbedSearch: TabbedSearch {
|
|||
groupSkip: 2px;
|
||||
height: 33px;
|
||||
}
|
||||
defaultEmojiPan: EmojiPan {
|
||||
margin: margins(7px, 0px, 7px, 0px);
|
||||
padding: margins(7px, 0px, 4px, 7px);
|
||||
desiredSize: 37px;
|
||||
verticalSizeSub: 1px;
|
||||
header: 33px;
|
||||
headerLeft: 14px;
|
||||
headerLockLeft: 7px;
|
||||
headerLockedLeft: 26px;
|
||||
headerTop: 10px;
|
||||
footer: 36px;
|
||||
iconSkip: 3px;
|
||||
iconWidth: 30px;
|
||||
iconArea: 28px;
|
||||
bg: emojiPanBg;
|
||||
overBg: emojiPanHover;
|
||||
expandBg: emojiPanHeaderFg;
|
||||
pathBg: windowBgRipple;
|
||||
pathFg: windowBgOver;
|
||||
textFg: windowFg;
|
||||
categoriesBg: emojiPanCategories;
|
||||
categoriesBgOver: windowBgRipple;
|
||||
fadeLeft: icon {{ "fade_horizontal-flip_horizontal", emojiPanCategories }};
|
||||
fadeRight: icon {{ "fade_horizontal", emojiPanCategories }};
|
||||
tabs: emojiTabs;
|
||||
search: defaultTabbedSearch;
|
||||
searchMargin: margins(1px, 11px, 2px, 5px);
|
||||
}
|
||||
statusEmojiPan: EmojiPan(defaultEmojiPan) {
|
||||
categoriesBg: windowBg;
|
||||
categoriesBgOver: windowBgOver;
|
||||
fadeLeft: icon {{ "fade_horizontal-flip_horizontal", windowBg }};
|
||||
fadeRight: icon {{ "fade_horizontal", windowBg }};
|
||||
}
|
||||
|
||||
inlineResultsMinHeight: 278px;
|
||||
inlineResultsMaxHeight: 640px;
|
||||
|
@ -394,6 +390,81 @@ stickersToast: Toast(defaultToast) {
|
|||
stickersEmpty: icon {{ "stickers_empty", windowSubTextFg }};
|
||||
emojiEmpty: icon {{ "emoji_empty", windowSubTextFg }};
|
||||
|
||||
defaultComposeIcons: ComposeIcons {
|
||||
settings: icon {{ "emoji/emoji_settings", emojiIconFg }};
|
||||
|
||||
recent: icon {{ "emoji/emoji_recent", emojiIconFg }};
|
||||
recentActive: icon {{ "emoji/emoji_recent", emojiSubIconFgActive }};
|
||||
people: icon {{ "emoji/emoji_smile", emojiIconFg }};
|
||||
peopleActive: icon {{ "emoji/emoji_smile", emojiSubIconFgActive }};
|
||||
nature: icon {{ "emoji/emoji_nature", emojiIconFg }};
|
||||
natureActive: icon {{ "emoji/emoji_nature", emojiSubIconFgActive }};
|
||||
food: icon {{ "emoji/emoji_food", emojiIconFg }};
|
||||
foodActive: icon {{ "emoji/emoji_food", emojiSubIconFgActive }};
|
||||
activity: icon {{ "emoji/emoji_activities", emojiIconFg }};
|
||||
activityActive: icon {{ "emoji/emoji_activities", emojiSubIconFgActive }};
|
||||
travel: icon {{ "emoji/emoji_travel", emojiIconFg }};
|
||||
travelActive: icon {{ "emoji/emoji_travel", emojiSubIconFgActive }};
|
||||
objects: icon {{ "emoji/emoji_objects", emojiIconFg }};
|
||||
objectsActive: icon {{ "emoji/emoji_objects", emojiSubIconFgActive }};
|
||||
symbols: icon {{ "emoji/emoji_love", emojiIconFg }};
|
||||
symbolsActive: icon {{ "emoji/emoji_love", emojiSubIconFgActive }};
|
||||
|
||||
menuFave: menuIconFave;
|
||||
menuUnfave: menuIconUnfave;
|
||||
menuStickerSet: menuIconStickers;
|
||||
menuRecentRemove: menuIconDelete;
|
||||
menuGifAdd: menuIconGif;
|
||||
menuGifRemove: menuIconDelete;
|
||||
menuMute: menuIconMute;
|
||||
menuSchedule: menuIconSchedule;
|
||||
menuWhenOnline: menuIconWhenOnline;
|
||||
}
|
||||
defaultEmojiPan: EmojiPan {
|
||||
margin: margins(7px, 0px, 7px, 0px);
|
||||
padding: margins(7px, 0px, 4px, 7px);
|
||||
showAnimation: emojiPanAnimation;
|
||||
desiredSize: 37px;
|
||||
verticalSizeSub: 1px;
|
||||
header: 33px;
|
||||
headerLeft: 14px;
|
||||
headerLockLeft: 7px;
|
||||
headerLockedLeft: 26px;
|
||||
headerTop: 10px;
|
||||
footer: 36px;
|
||||
iconSkip: 3px;
|
||||
iconWidth: 30px;
|
||||
iconArea: 28px;
|
||||
bg: emojiPanBg;
|
||||
headerFg: emojiPanHeaderFg;
|
||||
trendingHeaderFg: stickersTrendingHeaderFg;
|
||||
trendingSubheaderFg: stickersTrendingSubheaderFg;
|
||||
trendingUnreadFg: stickersFeaturedUnreadBg;
|
||||
trendingInstalled: stickersFeaturedInstalled;
|
||||
overBg: emojiPanHover;
|
||||
pathBg: windowBgRipple;
|
||||
pathFg: windowBgOver;
|
||||
textFg: windowFg;
|
||||
categoriesBg: emojiPanCategories;
|
||||
categoriesBgOver: windowBgRipple;
|
||||
fadeLeft: icon {{ "fade_horizontal-flip_horizontal", emojiPanCategories }};
|
||||
fadeRight: icon {{ "fade_horizontal", emojiPanCategories }};
|
||||
menu: popupMenuWithIcons;
|
||||
tabs: emojiTabs;
|
||||
search: defaultTabbedSearch;
|
||||
searchMargin: margins(1px, 11px, 2px, 5px);
|
||||
removeSet: stickerPanRemoveSet;
|
||||
boxLabel: boxLabel;
|
||||
icons: defaultComposeIcons;
|
||||
autocompleteBottomSkip: 0px;
|
||||
}
|
||||
statusEmojiPan: EmojiPan(defaultEmojiPan) {
|
||||
categoriesBg: windowBg;
|
||||
categoriesBgOver: windowBgOver;
|
||||
fadeLeft: icon {{ "fade_horizontal-flip_horizontal", windowBg }};
|
||||
fadeRight: icon {{ "fade_horizontal", windowBg }};
|
||||
}
|
||||
|
||||
inlineBotsScroll: ScrollArea(defaultSolidScroll) {
|
||||
deltat: stickerPanPadding;
|
||||
deltab: stickerPanPadding;
|
||||
|
@ -410,6 +481,15 @@ emojiSuggestionsScrolledWidth: 240px;
|
|||
emojiSuggestionsPadding: margins(emojiColorsPadding, 0px, emojiColorsPadding, 0px);
|
||||
emojiSuggestionsFadeAfter: 20px;
|
||||
|
||||
defaultEmojiSuggestions: EmojiSuggestions {
|
||||
dropdown: emojiSuggestionsDropdown;
|
||||
bg: menuBg;
|
||||
overBg: emojiPanHover;
|
||||
textFg: windowFg;
|
||||
fadeLeft: icon {{ "fade_horizontal-flip_horizontal", boxBg }};
|
||||
fadeRight: icon {{ "fade_horizontal", boxBg }};
|
||||
}
|
||||
|
||||
mentionHeight: 40px;
|
||||
mentionPadding: margins(8px, 5px, 8px, 5px);
|
||||
mentionTop: 11px;
|
||||
|
@ -479,9 +559,6 @@ reactPanelScroll: ScrollArea(emojiScroll) {
|
|||
deltab: 7px;
|
||||
}
|
||||
|
||||
emojiSuggestionsFadeLeft: icon {{ "fade_horizontal-flip_horizontal", boxBg }};
|
||||
emojiSuggestionsFadeRight: icon {{ "fade_horizontal", boxBg }};
|
||||
|
||||
choosePeerGroupIcon: icon {{ "info/edit/create_group", lightButtonFg }};
|
||||
choosePeerChannelIcon: icon {{ "info/edit/create_channel", lightButtonFg }};
|
||||
choosePeerCreateIconLeft: 25px;
|
||||
|
@ -857,5 +934,6 @@ defaultComposeControls: ComposeControls {
|
|||
send: historySend;
|
||||
attach: historyAttach;
|
||||
emoji: historyAttachEmoji;
|
||||
suggestions: defaultEmojiSuggestions;
|
||||
tabbed: defaultEmojiPan;
|
||||
}
|
||||
|
|
27
Telegram/SourceFiles/chat_helpers/compose/compose_features.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
namespace ChatHelpers {
|
||||
|
||||
struct ComposeFeatures {
|
||||
bool sendAs = true;
|
||||
bool ttlInfo = true;
|
||||
bool botCommandSend = true;
|
||||
bool silentBroadcastToggle = true;
|
||||
bool attachBotsMenu = true;
|
||||
bool inlineBots = true;
|
||||
bool megagroupSet = true;
|
||||
bool stickersSettings = true;
|
||||
bool openStickerSets = true;
|
||||
bool autocompleteHashtags = true;
|
||||
bool autocompleteMentions = true;
|
||||
bool autocompleteCommands = true;
|
||||
};
|
||||
|
||||
} // namespace ChatHelpers
|
|
@ -99,6 +99,7 @@ private:
|
|||
QSize _singleSize;
|
||||
QPoint _areaPosition;
|
||||
QPoint _innerPosition;
|
||||
Ui::RoundRect _backgroundRect;
|
||||
Ui::RoundRect _overBg;
|
||||
|
||||
bool _hiding = false;
|
||||
|
@ -125,6 +126,7 @@ EmojiColorPicker::EmojiColorPicker(
|
|||
const style::EmojiPan &st)
|
||||
: RpWidget(parent)
|
||||
, _st(st)
|
||||
, _backgroundRect(st::emojiPanRadius, _st.bg)
|
||||
, _overBg(st::emojiPanRadius, _st.overBg) {
|
||||
setMouseTracking(true);
|
||||
}
|
||||
|
@ -181,8 +183,8 @@ void EmojiColorPicker::paintEvent(QPaintEvent *e) {
|
|||
p.drawPixmap(0, 0, _cache);
|
||||
return;
|
||||
}
|
||||
Ui::Shadow::paint(p, inner, width(), st::emojiPanAnimation.shadow);
|
||||
Ui::FillRoundRect(p, inner, st::boxBg, Ui::BoxCorners);
|
||||
Ui::Shadow::paint(p, inner, width(), _st.showAnimation.shadow);
|
||||
_backgroundRect.paint(p, inner);
|
||||
|
||||
auto x = st::emojiPanMargins.left() + 2 * st::emojiColorsPadding + _singleSize.width();
|
||||
if (rtl()) x = width() - x - st::emojiColorsSep;
|
||||
|
@ -393,6 +395,7 @@ EmojiListWidget::EmojiListWidget(
|
|||
descriptor.show,
|
||||
std::move(descriptor.paused))
|
||||
, _show(std::move(descriptor.show))
|
||||
, _features(descriptor.features)
|
||||
, _mode(descriptor.mode)
|
||||
, _staticCount(_mode == Mode::Full ? kEmojiSectionCount : 1)
|
||||
, _premiumIcon(_mode == Mode::EmojiStatus
|
||||
|
@ -402,7 +405,7 @@ EmojiListWidget::EmojiListWidget(
|
|||
std::make_unique<LocalStickersManager>(&session()))
|
||||
, _customRecentFactory(std::move(descriptor.customRecentFactory))
|
||||
, _overBg(st::emojiPanRadius, st().overBg)
|
||||
, _collapsedBg(st::emojiPanExpand.height / 2, st::emojiPanHeaderFg)
|
||||
, _collapsedBg(st::emojiPanExpand.height / 2, st().headerFg)
|
||||
, _picker(this, st())
|
||||
, _showPickerTimer([=] { showPicker(); }) {
|
||||
setMouseTracking(true);
|
||||
|
@ -1072,7 +1075,7 @@ void EmojiListWidget::paint(
|
|||
- paintButtonGetWidth(p, info, buttonSelected, clip);
|
||||
if (info.section > 0 && clip.top() < info.rowsTop) {
|
||||
p.setFont(st::emojiPanHeaderFont);
|
||||
p.setPen(st::emojiPanHeaderFg);
|
||||
p.setPen(st().headerFg);
|
||||
auto titleText = (info.section < _staticCount)
|
||||
? ChatHelpers::EmojiCategoryTitle(info.section)(tr::now)
|
||||
: _custom[info.section - _staticCount].title;
|
||||
|
@ -1091,7 +1094,7 @@ void EmojiListWidget::paint(
|
|||
}
|
||||
const auto textBaseline = top + st::emojiPanHeaderFont->ascent;
|
||||
p.setFont(st::emojiPanHeaderFont);
|
||||
p.setPen(st::emojiPanHeaderFg);
|
||||
p.setPen(st().headerFg);
|
||||
p.drawText(titleLeft, textBaseline, titleText);
|
||||
}
|
||||
if (clip.top() + clip.height() > info.rowsTop) {
|
||||
|
@ -1459,7 +1462,8 @@ void EmojiListWidget::displaySet(uint64 setId) {
|
|||
}
|
||||
|
||||
void EmojiListWidget::removeSet(uint64 setId) {
|
||||
if (auto box = MakeConfirmRemoveSetBox(&session(), setId)) {
|
||||
const auto &labelSt = st().boxLabel;
|
||||
if (auto box = MakeConfirmRemoveSetBox(&session(), labelSt, setId)) {
|
||||
checkHideWithBox(std::move(box));
|
||||
}
|
||||
}
|
||||
|
@ -1532,9 +1536,10 @@ QRect EmojiListWidget::removeButtonRect(const SectionInfo &info) const {
|
|||
if (_mode != Mode::Full) {
|
||||
return QRect();
|
||||
}
|
||||
const auto buttonw = st::stickerPanRemoveSet.rippleAreaPosition.x()
|
||||
+ st::stickerPanRemoveSet.rippleAreaSize;
|
||||
const auto buttonh = st::stickerPanRemoveSet.height;
|
||||
const auto &removeSt = st().removeSet;
|
||||
const auto buttonw = removeSt.rippleAreaPosition.x()
|
||||
+ removeSt.rippleAreaSize;
|
||||
const auto buttonh = removeSt.height;
|
||||
const auto buttonx = emojiRight() - st::emojiPanRemoveSkip - buttonw;
|
||||
const auto buttony = info.top + st::emojiPanRemoveTop;
|
||||
return QRect(buttonx, buttony, buttonw, buttonh);
|
||||
|
@ -1966,19 +1971,18 @@ int EmojiListWidget::paintButtonGetWidth(
|
|||
if (remove.isEmpty()) {
|
||||
return 0;
|
||||
} else if (remove.intersects(clip)) {
|
||||
const auto &removeSt = st().removeSet;
|
||||
if (custom.ripple) {
|
||||
custom.ripple->paint(
|
||||
p,
|
||||
remove.x() + st::stickerPanRemoveSet.rippleAreaPosition.x(),
|
||||
remove.y() + st::stickerPanRemoveSet.rippleAreaPosition.y(),
|
||||
remove.x() + removeSt.rippleAreaPosition.x(),
|
||||
remove.y() + removeSt.rippleAreaPosition.y(),
|
||||
width());
|
||||
if (custom.ripple->empty()) {
|
||||
custom.ripple.reset();
|
||||
}
|
||||
}
|
||||
const auto &icon = selected
|
||||
? st::stickerPanRemoveSet.iconOver
|
||||
: st::stickerPanRemoveSet.icon;
|
||||
const auto &icon = selected ? removeSt.iconOver : removeSt.icon;
|
||||
icon.paint(
|
||||
p,
|
||||
(remove.topLeft()
|
||||
|
@ -2045,7 +2049,9 @@ void EmojiListWidget::updateSelected() {
|
|||
if (hasButton(section)
|
||||
&& myrtlrect(buttonRect(section)).contains(p.x(), p.y())) {
|
||||
newSelected = OverButton{ section };
|
||||
} else if (section >= _staticCount && _mode == Mode::Full) {
|
||||
} else if (_features.openStickerSets
|
||||
&& section >= _staticCount
|
||||
&& _mode == Mode::Full) {
|
||||
newSelected = OverSet{ section };
|
||||
}
|
||||
} else if (p.y() >= info.rowsTop && p.y() < info.rowsBottom) {
|
||||
|
@ -2159,13 +2165,12 @@ std::unique_ptr<Ui::RippleAnimation> EmojiListWidget::createButtonRipple(
|
|||
&& section < _staticCount + _custom.size());
|
||||
|
||||
const auto remove = hasRemoveButton(section);
|
||||
const auto &st = remove
|
||||
? st::stickerPanRemoveSet.ripple
|
||||
: st::emojiPanButton.ripple;
|
||||
const auto &removeSt = st().removeSet;
|
||||
const auto &st = remove ? removeSt.ripple : st::emojiPanButton.ripple;
|
||||
auto mask = remove
|
||||
? Ui::RippleAnimation::EllipseMask(QSize(
|
||||
st::stickerPanRemoveSet.rippleAreaSize,
|
||||
st::stickerPanRemoveSet.rippleAreaSize))
|
||||
removeSt.rippleAreaSize,
|
||||
removeSt.rippleAreaSize))
|
||||
: rightButton(section).rippleMask;
|
||||
return std::make_unique<Ui::RippleAnimation>(
|
||||
st,
|
||||
|
@ -2179,7 +2184,7 @@ QPoint EmojiListWidget::buttonRippleTopLeft(int section) const {
|
|||
|
||||
return myrtlrect(buttonRect(section)).topLeft()
|
||||
+ (hasRemoveButton(section)
|
||||
? st::stickerPanRemoveSet.rippleAreaPosition
|
||||
? st().removeSet.rippleAreaPosition
|
||||
: QPoint());
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "chat_helpers/compose/compose_features.h"
|
||||
#include "chat_helpers/tabbed_selector.h"
|
||||
#include "ui/widgets/tooltip.h"
|
||||
#include "ui/round_rect.h"
|
||||
|
@ -84,6 +85,7 @@ struct EmojiListDescriptor {
|
|||
DocumentId,
|
||||
Fn<void()>)> customRecentFactory;
|
||||
const style::EmojiPan *st = nullptr;
|
||||
ComposeFeatures features;
|
||||
};
|
||||
|
||||
class EmojiListWidget final
|
||||
|
@ -345,6 +347,7 @@ private:
|
|||
void applyNextSearchQuery();
|
||||
|
||||
const std::shared_ptr<Show> _show;
|
||||
const ComposeFeatures _features;
|
||||
Mode _mode = Mode::Full;
|
||||
std::unique_ptr<Ui::TabbedSearch> _search;
|
||||
const int _staticCount = 0;
|
||||
|
|
|
@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/emoji_config.h"
|
||||
#include "ui/ui_utility.h"
|
||||
#include "ui/cached_round_corners.h"
|
||||
#include "ui/round_rect.h"
|
||||
#include "platform/platform_specific.h"
|
||||
#include "core/application.h"
|
||||
#include "base/event_filter.h"
|
||||
|
@ -41,15 +42,133 @@ constexpr auto kAnimationDuration = crl::time(120);
|
|||
|
||||
} // namespace
|
||||
|
||||
class SuggestionsWidget final : public Ui::RpWidget {
|
||||
public:
|
||||
SuggestionsWidget(
|
||||
QWidget *parent,
|
||||
const style::EmojiSuggestions &st,
|
||||
not_null<Main::Session*> session,
|
||||
bool suggestCustomEmoji,
|
||||
Fn<bool(not_null<DocumentData*>)> allowCustomWithoutPremium);
|
||||
~SuggestionsWidget();
|
||||
|
||||
void showWithQuery(SuggestionsQuery query, bool force = false);
|
||||
void selectFirstResult();
|
||||
bool handleKeyEvent(int key);
|
||||
|
||||
[[nodiscard]] rpl::producer<bool> toggleAnimated() const;
|
||||
|
||||
struct Chosen {
|
||||
QString emoji;
|
||||
QString customData;
|
||||
};
|
||||
[[nodiscard]] rpl::producer<Chosen> triggered() const;
|
||||
|
||||
private:
|
||||
struct Row {
|
||||
Row(not_null<EmojiPtr> emoji, const QString &replacement);
|
||||
|
||||
Ui::Text::CustomEmoji *custom = nullptr;
|
||||
DocumentData *document = nullptr;
|
||||
not_null<EmojiPtr> emoji;
|
||||
QString replacement;
|
||||
};
|
||||
struct Custom {
|
||||
not_null<DocumentData*> document;
|
||||
not_null<EmojiPtr> emoji;
|
||||
QString replacement;
|
||||
};
|
||||
|
||||
bool eventHook(QEvent *e) override;
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
void mouseMoveEvent(QMouseEvent *e) override;
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
void enterEventHook(QEnterEvent *e) override;
|
||||
void leaveEventHook(QEvent *e) override;
|
||||
|
||||
void scrollByWheelEvent(not_null<QWheelEvent*> e);
|
||||
void paintFadings(QPainter &p) const;
|
||||
|
||||
[[nodiscard]] std::vector<Row> getRowsByQuery(const QString &text) const;
|
||||
[[nodiscard]] base::flat_multi_map<int, Custom> lookupCustom(
|
||||
const std::vector<Row> &rows) const;
|
||||
[[nodiscard]] std::vector<Row> appendCustom(
|
||||
std::vector<Row> rows);
|
||||
[[nodiscard]] std::vector<Row> appendCustom(
|
||||
std::vector<Row> rows,
|
||||
const base::flat_multi_map<int, Custom> &custom);
|
||||
void resizeToRows();
|
||||
void setSelected(
|
||||
int selected,
|
||||
anim::type animated = anim::type::instant);
|
||||
void setPressed(int pressed);
|
||||
void clearMouseSelection();
|
||||
void clearSelection();
|
||||
void updateSelectedItem();
|
||||
void updateItem(int index);
|
||||
[[nodiscard]] QRect inner() const;
|
||||
[[nodiscard]] QPoint innerShift() const;
|
||||
[[nodiscard]] QPoint mapToInner(QPoint globalPosition) const;
|
||||
void selectByMouse(QPoint globalPosition);
|
||||
bool triggerSelectedRow() const;
|
||||
void triggerRow(const Row &row) const;
|
||||
|
||||
[[nodiscard]] int scrollCurrent() const;
|
||||
void scrollTo(int value, anim::type animated = anim::type::instant);
|
||||
void stopAnimations();
|
||||
|
||||
[[nodiscard]] not_null<Ui::Text::CustomEmoji*> resolveCustomEmoji(
|
||||
not_null<DocumentData*> document);
|
||||
void customEmojiRepaint();
|
||||
|
||||
const style::EmojiSuggestions &_st;
|
||||
const not_null<Main::Session*> _session;
|
||||
SuggestionsQuery _query;
|
||||
std::vector<Row> _rows;
|
||||
bool _suggestCustomEmoji = false;
|
||||
Fn<bool(not_null<DocumentData*>)> _allowCustomWithoutPremium;
|
||||
|
||||
Ui::RoundRect _overRect;
|
||||
|
||||
base::flat_map<
|
||||
not_null<DocumentData*>,
|
||||
std::unique_ptr<Ui::Text::CustomEmoji>> _customEmoji;
|
||||
bool _repaintScheduled = false;
|
||||
|
||||
std::optional<QPoint> _lastMousePosition;
|
||||
bool _mouseSelection = false;
|
||||
int _selected = -1;
|
||||
int _pressed = -1;
|
||||
|
||||
int _scrollValue = 0;
|
||||
Ui::Animations::Simple _scrollAnimation;
|
||||
Ui::Animations::Simple _selectedAnimation;
|
||||
int _scrollMax = 0;
|
||||
int _oneWidth = 0;
|
||||
QMargins _padding;
|
||||
|
||||
QPoint _mousePressPosition;
|
||||
int _dragScrollStart = -1;
|
||||
|
||||
rpl::event_stream<bool> _toggleAnimated;
|
||||
rpl::event_stream<Chosen> _triggered;
|
||||
|
||||
};
|
||||
|
||||
SuggestionsWidget::SuggestionsWidget(
|
||||
QWidget *parent,
|
||||
const style::EmojiSuggestions &st,
|
||||
not_null<Main::Session*> session,
|
||||
bool suggestCustomEmoji,
|
||||
Fn<bool(not_null<DocumentData*>)> allowCustomWithoutPremium)
|
||||
: RpWidget(parent)
|
||||
, _st(st)
|
||||
, _session(session)
|
||||
, _suggestCustomEmoji(suggestCustomEmoji)
|
||||
, _allowCustomWithoutPremium(std::move(allowCustomWithoutPremium))
|
||||
, _overRect(st::roundRadiusSmall, _st.overBg)
|
||||
, _oneWidth(st::emojiSuggestionSize)
|
||||
, _padding(st::emojiSuggestionsPadding) {
|
||||
resize(
|
||||
|
@ -284,7 +403,7 @@ void SuggestionsWidget::paintEvent(QPaintEvent *e) {
|
|||
_repaintScheduled = false;
|
||||
|
||||
const auto clip = e->rect();
|
||||
p.fillRect(clip, st::boxBg);
|
||||
p.fillRect(clip, _st.bg);
|
||||
|
||||
const auto shift = innerShift();
|
||||
p.translate(-shift);
|
||||
|
@ -298,15 +417,13 @@ void SuggestionsWidget::paintEvent(QPaintEvent *e) {
|
|||
? _pressed
|
||||
: _selectedAnimation.value(_selected);
|
||||
if (selected > -1.) {
|
||||
Ui::FillRoundRect(
|
||||
_overRect.paint(
|
||||
p,
|
||||
QRect(selected * _oneWidth, 0, _oneWidth, _oneWidth),
|
||||
st::emojiPanHover,
|
||||
Ui::StickerHoverCorners);
|
||||
QRect(selected * _oneWidth, 0, _oneWidth, _oneWidth));
|
||||
}
|
||||
|
||||
auto context = Ui::CustomEmoji::Context{
|
||||
.textColor = st::windowFg->c,
|
||||
.textColor = _st.textFg->c,
|
||||
.now = crl::now(),
|
||||
};
|
||||
for (auto i = from; i != till; ++i) {
|
||||
|
@ -338,9 +455,9 @@ void SuggestionsWidget::paintFadings(QPainter &p) const {
|
|||
const auto rect = myrtlrect(
|
||||
shift.x(),
|
||||
0,
|
||||
st::emojiSuggestionsFadeLeft.width(),
|
||||
_st.fadeLeft.width(),
|
||||
height());
|
||||
st::emojiSuggestionsFadeLeft.fill(p, rect);
|
||||
_st.fadeLeft.fill(p, rect);
|
||||
p.setOpacity(1.);
|
||||
}
|
||||
const auto o_right = std::clamp(
|
||||
|
@ -350,11 +467,11 @@ void SuggestionsWidget::paintFadings(QPainter &p) const {
|
|||
if (o_right > 0.) {
|
||||
p.setOpacity(o_right);
|
||||
const auto rect = myrtlrect(
|
||||
shift.x() + width() - st::emojiSuggestionsFadeRight.width(),
|
||||
shift.x() + width() - _st.fadeRight.width(),
|
||||
0,
|
||||
st::emojiSuggestionsFadeRight.width(),
|
||||
_st.fadeRight.width(),
|
||||
height());
|
||||
st::emojiSuggestionsFadeRight.fill(p, rect);
|
||||
_st.fadeRight.fill(p, rect);
|
||||
p.setOpacity(1.);
|
||||
}
|
||||
}
|
||||
|
@ -601,17 +718,17 @@ SuggestionsController::SuggestionsController(
|
|||
not_null<QTextEdit*> field,
|
||||
not_null<Main::Session*> session,
|
||||
const Options &options)
|
||||
: _field(field)
|
||||
: _st(options.st ? *options.st : st::defaultEmojiSuggestions)
|
||||
, _field(field)
|
||||
, _session(session)
|
||||
, _showExactTimer([=] { showWithQuery(getEmojiQuery()); })
|
||||
, _options(options) {
|
||||
_container = base::make_unique_q<InnerDropdown>(
|
||||
outer,
|
||||
st::emojiSuggestionsDropdown);
|
||||
_container = base::make_unique_q<InnerDropdown>(outer, _st.dropdown);
|
||||
_container->setAutoHiding(false);
|
||||
_suggestions = _container->setOwnedWidget(
|
||||
object_ptr<Ui::Emoji::SuggestionsWidget>(
|
||||
_container,
|
||||
_st,
|
||||
session,
|
||||
_options.suggestCustomEmoji,
|
||||
_options.allowCustomWithoutPremium));
|
||||
|
@ -910,7 +1027,7 @@ void SuggestionsController::updateGeometry() {
|
|||
auto boundingRect = _container->parentWidget()->rect();
|
||||
auto origin = rtl() ? PanelAnimation::Origin::BottomRight : PanelAnimation::Origin::BottomLeft;
|
||||
auto point = rtl() ? (aroundRect.topLeft() + QPoint(aroundRect.width(), 0)) : aroundRect.topLeft();
|
||||
const auto padding = st::emojiSuggestionsDropdown.padding;
|
||||
const auto padding = _st.dropdown.padding;
|
||||
const auto shift = std::min(_container->width() - padding.left() - padding.right(), st::emojiSuggestionSize) / 2;
|
||||
point -= rtl() ? QPoint(_container->width() - padding.right() - shift, _container->height()) : QPoint(padding.left() + shift, _container->height());
|
||||
if (rtl()) {
|
||||
|
|
|
@ -14,6 +14,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include <QtWidgets/QTextEdit>
|
||||
|
||||
namespace style {
|
||||
struct EmojiSuggestions;
|
||||
} // namespace style
|
||||
|
||||
namespace Main {
|
||||
class Session;
|
||||
} // namespace Main
|
||||
|
@ -29,125 +33,17 @@ class CustomEmoji;
|
|||
|
||||
namespace Ui::Emoji {
|
||||
|
||||
class SuggestionsWidget;
|
||||
|
||||
using SuggestionsQuery = std::variant<QString, EmojiPtr>;
|
||||
|
||||
class SuggestionsWidget final : public Ui::RpWidget {
|
||||
public:
|
||||
SuggestionsWidget(
|
||||
QWidget *parent,
|
||||
not_null<Main::Session*> session,
|
||||
bool suggestCustomEmoji,
|
||||
Fn<bool(not_null<DocumentData*>)> allowCustomWithoutPremium);
|
||||
~SuggestionsWidget();
|
||||
|
||||
void showWithQuery(SuggestionsQuery query, bool force = false);
|
||||
void selectFirstResult();
|
||||
bool handleKeyEvent(int key);
|
||||
|
||||
[[nodiscard]] rpl::producer<bool> toggleAnimated() const;
|
||||
|
||||
struct Chosen {
|
||||
QString emoji;
|
||||
QString customData;
|
||||
};
|
||||
[[nodiscard]] rpl::producer<Chosen> triggered() const;
|
||||
|
||||
private:
|
||||
struct Row {
|
||||
Row(not_null<EmojiPtr> emoji, const QString &replacement);
|
||||
|
||||
Ui::Text::CustomEmoji *custom = nullptr;
|
||||
DocumentData *document = nullptr;
|
||||
not_null<EmojiPtr> emoji;
|
||||
QString replacement;
|
||||
};
|
||||
struct Custom {
|
||||
not_null<DocumentData*> document;
|
||||
not_null<EmojiPtr> emoji;
|
||||
QString replacement;
|
||||
};
|
||||
|
||||
bool eventHook(QEvent *e) override;
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
void mouseMoveEvent(QMouseEvent *e) override;
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
void enterEventHook(QEnterEvent *e) override;
|
||||
void leaveEventHook(QEvent *e) override;
|
||||
|
||||
void scrollByWheelEvent(not_null<QWheelEvent*> e);
|
||||
void paintFadings(QPainter &p) const;
|
||||
|
||||
[[nodiscard]] std::vector<Row> getRowsByQuery(const QString &text) const;
|
||||
[[nodiscard]] base::flat_multi_map<int, Custom> lookupCustom(
|
||||
const std::vector<Row> &rows) const;
|
||||
[[nodiscard]] std::vector<Row> appendCustom(
|
||||
std::vector<Row> rows);
|
||||
[[nodiscard]] std::vector<Row> appendCustom(
|
||||
std::vector<Row> rows,
|
||||
const base::flat_multi_map<int, Custom> &custom);
|
||||
void resizeToRows();
|
||||
void setSelected(
|
||||
int selected,
|
||||
anim::type animated = anim::type::instant);
|
||||
void setPressed(int pressed);
|
||||
void clearMouseSelection();
|
||||
void clearSelection();
|
||||
void updateSelectedItem();
|
||||
void updateItem(int index);
|
||||
[[nodiscard]] QRect inner() const;
|
||||
[[nodiscard]] QPoint innerShift() const;
|
||||
[[nodiscard]] QPoint mapToInner(QPoint globalPosition) const;
|
||||
void selectByMouse(QPoint globalPosition);
|
||||
bool triggerSelectedRow() const;
|
||||
void triggerRow(const Row &row) const;
|
||||
|
||||
[[nodiscard]] int scrollCurrent() const;
|
||||
void scrollTo(int value, anim::type animated = anim::type::instant);
|
||||
void stopAnimations();
|
||||
|
||||
[[nodiscard]] not_null<Ui::Text::CustomEmoji*> resolveCustomEmoji(
|
||||
not_null<DocumentData*> document);
|
||||
void customEmojiRepaint();
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
SuggestionsQuery _query;
|
||||
std::vector<Row> _rows;
|
||||
bool _suggestCustomEmoji = false;
|
||||
Fn<bool(not_null<DocumentData*>)> _allowCustomWithoutPremium;
|
||||
|
||||
base::flat_map<
|
||||
not_null<DocumentData*>,
|
||||
std::unique_ptr<Ui::Text::CustomEmoji>> _customEmoji;
|
||||
bool _repaintScheduled = false;
|
||||
|
||||
std::optional<QPoint> _lastMousePosition;
|
||||
bool _mouseSelection = false;
|
||||
int _selected = -1;
|
||||
int _pressed = -1;
|
||||
|
||||
int _scrollValue = 0;
|
||||
Ui::Animations::Simple _scrollAnimation;
|
||||
Ui::Animations::Simple _selectedAnimation;
|
||||
int _scrollMax = 0;
|
||||
int _oneWidth = 0;
|
||||
QMargins _padding;
|
||||
|
||||
QPoint _mousePressPosition;
|
||||
int _dragScrollStart = -1;
|
||||
|
||||
rpl::event_stream<bool> _toggleAnimated;
|
||||
rpl::event_stream<Chosen> _triggered;
|
||||
|
||||
};
|
||||
|
||||
class SuggestionsController {
|
||||
public:
|
||||
struct Options {
|
||||
bool suggestExactFirstWord = true;
|
||||
bool suggestCustomEmoji = false;
|
||||
Fn<bool(not_null<DocumentData*>)> allowCustomWithoutPremium;
|
||||
const style::EmojiSuggestions *st = nullptr;
|
||||
};
|
||||
|
||||
SuggestionsController(
|
||||
|
@ -189,6 +85,7 @@ private:
|
|||
bool fieldFilter(not_null<QEvent*> event);
|
||||
bool outerFilter(not_null<QEvent*> event);
|
||||
|
||||
const style::EmojiSuggestions &_st;
|
||||
bool _shown = false;
|
||||
bool _forceHidden = false;
|
||||
int _queryStartPosition = 0;
|
||||
|
|
|
@ -685,6 +685,7 @@ void FieldAutocomplete::recount(bool resetScroll) {
|
|||
} else if (!_brows.empty()) {
|
||||
h = _brows.size() * st::mentionHeight;
|
||||
}
|
||||
h += _st.autocompleteBottomSkip;
|
||||
|
||||
if (_inner->width() != _boundings.width() || _inner->height() != h) {
|
||||
_inner->resize(_boundings.width(), h);
|
||||
|
@ -1375,8 +1376,10 @@ void FieldAutocomplete::Inner::setSel(int sel, bool scroll) {
|
|||
int32 row = _sel / _stickersPerRow;
|
||||
const auto padding = st::stickerPanPadding;
|
||||
_scrollToRequested.fire({
|
||||
padding + row * st::stickerPanSize.height(),
|
||||
padding + (row + 1) * st::stickerPanSize.height() });
|
||||
(row ? padding : 0) + row * st::stickerPanSize.height(),
|
||||
(padding
|
||||
+ (row + 1) * st::stickerPanSize.height()
|
||||
+ _st.autocompleteBottomSkip) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,8 @@ constexpr auto kMinAfterScrollDelay = crl::time(33);
|
|||
void AddGifAction(
|
||||
Fn<void(QString, Fn<void()> &&, const style::icon*)> callback,
|
||||
std::shared_ptr<Show> show,
|
||||
not_null<DocumentData*> document) {
|
||||
not_null<DocumentData*> document,
|
||||
const style::ComposeIcons *iconsOverride) {
|
||||
if (!document->isGifv()) {
|
||||
return;
|
||||
}
|
||||
|
@ -67,6 +68,9 @@ void AddGifAction(
|
|||
const auto text = (saved
|
||||
? tr::lng_context_delete_gif
|
||||
: tr::lng_context_save_gif)(tr::now);
|
||||
const auto &icons = iconsOverride
|
||||
? *iconsOverride
|
||||
: st::defaultComposeIcons;
|
||||
callback(text, [=] {
|
||||
Api::ToggleSavedGif(
|
||||
show,
|
||||
|
@ -80,7 +84,7 @@ void AddGifAction(
|
|||
document->session().local().writeSavedGifs();
|
||||
}
|
||||
data.stickers().notifySavedGifsUpdated();
|
||||
}, saved ? &st::menuIconDelete : &st::menuIconGif);
|
||||
}, saved ? &icons.menuGifRemove : &icons.menuGifAdd);
|
||||
}
|
||||
|
||||
GifsListWidget::GifsListWidget(
|
||||
|
@ -380,18 +384,18 @@ base::unique_qptr<Ui::PopupMenu> GifsListWidget::fillContextMenu(
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
auto menu = base::make_unique_q<Ui::PopupMenu>(
|
||||
this,
|
||||
st::popupMenuWithIcons);
|
||||
auto menu = base::make_unique_q<Ui::PopupMenu>(this, st().menu);
|
||||
const auto send = [=, selected = _selected](Api::SendOptions options) {
|
||||
selectInlineResult(selected, options, true);
|
||||
};
|
||||
const auto icons = &st().icons;
|
||||
SendMenu::FillSendMenu(
|
||||
menu,
|
||||
type,
|
||||
SendMenu::DefaultSilentCallback(send),
|
||||
SendMenu::DefaultScheduleCallback(this, type, send),
|
||||
SendMenu::DefaultWhenOnlineCallback(send));
|
||||
SendMenu::DefaultWhenOnlineCallback(send),
|
||||
icons);
|
||||
|
||||
if (const auto item = _mosaic.maybeItemAt(_selected)) {
|
||||
const auto document = item->getDocument()
|
||||
|
@ -404,7 +408,7 @@ base::unique_qptr<Ui::PopupMenu> GifsListWidget::fillContextMenu(
|
|||
const style::icon *icon) {
|
||||
menu->addAction(text, std::move(done), icon);
|
||||
};
|
||||
AddGifAction(std::move(callback), _show, document);
|
||||
AddGifAction(std::move(callback), _show, document, icons);
|
||||
}
|
||||
}
|
||||
return menu;
|
||||
|
|
|
@ -14,6 +14,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include <QtCore/QTimer>
|
||||
|
||||
namespace style {
|
||||
struct ComposeIcons;
|
||||
} // namespace style
|
||||
|
||||
namespace Api {
|
||||
struct SendOptions;
|
||||
} // namespace Api
|
||||
|
@ -48,7 +52,8 @@ namespace ChatHelpers {
|
|||
void AddGifAction(
|
||||
Fn<void(QString, Fn<void()> &&, const style::icon*)> callback,
|
||||
std::shared_ptr<Show> show,
|
||||
not_null<DocumentData*> document);
|
||||
not_null<DocumentData*> document,
|
||||
const style::ComposeIcons *iconsOverride = nullptr);
|
||||
|
||||
class StickersListFooter;
|
||||
struct StickerIcon;
|
||||
|
|
|
@ -498,7 +498,8 @@ InlineBotQuery ParseInlineBotQuery(
|
|||
}
|
||||
|
||||
AutocompleteQuery ParseMentionHashtagBotCommandQuery(
|
||||
not_null<const Ui::InputField*> field) {
|
||||
not_null<const Ui::InputField*> field,
|
||||
ChatHelpers::ComposeFeatures features) {
|
||||
auto result = AutocompleteQuery();
|
||||
|
||||
const auto cursor = field->textCursor();
|
||||
|
@ -530,6 +531,9 @@ AutocompleteQuery ParseMentionHashtagBotCommandQuery(
|
|||
const auto text = fragment.text();
|
||||
for (auto i = position - fragmentPosition; i != 0; --i) {
|
||||
if (text[i - 1] == '@') {
|
||||
if (!features.autocompleteMentions) {
|
||||
return {};
|
||||
}
|
||||
if ((position - fragmentPosition - i < 1 || text[i].isLetter()) && (i < 2 || !(text[i - 2].isLetterOrNumber() || text[i - 2] == '_'))) {
|
||||
result.fromStart = (i == 1) && (fragmentPosition == 0);
|
||||
result.query = text.mid(i - 1, position - fragmentPosition - i + 1);
|
||||
|
@ -540,12 +544,18 @@ AutocompleteQuery ParseMentionHashtagBotCommandQuery(
|
|||
}
|
||||
return result;
|
||||
} else if (text[i - 1] == '#') {
|
||||
if (!features.autocompleteHashtags) {
|
||||
return {};
|
||||
}
|
||||
if (i < 2 || !(text[i - 2].isLetterOrNumber() || text[i - 2] == '_')) {
|
||||
result.fromStart = (i == 1) && (fragmentPosition == 0);
|
||||
result.query = text.mid(i - 1, position - fragmentPosition - i + 1);
|
||||
}
|
||||
return result;
|
||||
} else if (text[i - 1] == '/') {
|
||||
if (!features.autocompleteCommands) {
|
||||
return {};
|
||||
}
|
||||
if (i < 2 && !fragmentPosition) {
|
||||
result.fromStart = (i == 1) && (fragmentPosition == 0);
|
||||
result.query = text.mid(i - 1, position - fragmentPosition - i + 1);
|
||||
|
|
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/widgets/input_fields.h"
|
||||
#include "base/timer.h"
|
||||
#include "base/qt_connection.h"
|
||||
#include "chat_helpers/compose/compose_features.h"
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_SPELLCHECK
|
||||
#include "boxes/dictionaries_manager.h"
|
||||
|
@ -90,7 +91,8 @@ struct AutocompleteQuery {
|
|||
bool fromStart = false;
|
||||
};
|
||||
AutocompleteQuery ParseMentionHashtagBotCommandQuery(
|
||||
not_null<const Ui::InputField*> field);
|
||||
not_null<const Ui::InputField*> field,
|
||||
ChatHelpers::ComposeFeatures features);
|
||||
|
||||
class MessageLinksParser : private QObject {
|
||||
public:
|
||||
|
|
|
@ -292,7 +292,7 @@ StickersListFooter::StickersListFooter(Descriptor &&descriptor)
|
|||
descriptor.st ? *descriptor.st : st::defaultEmojiPan)
|
||||
, _session(descriptor.session)
|
||||
, _paused(descriptor.paused)
|
||||
, _settingsButtonVisible(descriptor.settingsButtonVisible)
|
||||
, _features(descriptor.features)
|
||||
, _iconState([=] { update(); })
|
||||
, _subiconState([=] { update(); })
|
||||
, _selectionBg(st::emojiPanRadius, st().categoriesBgOver)
|
||||
|
@ -300,7 +300,7 @@ StickersListFooter::StickersListFooter(Descriptor &&descriptor)
|
|||
setMouseTracking(true);
|
||||
|
||||
_iconsLeft = st().iconSkip
|
||||
+ (_settingsButtonVisible ? st().iconWidth : 0);
|
||||
+ (_features.stickersSettings ? st().iconWidth : 0);
|
||||
_iconsRight = st().iconSkip;
|
||||
|
||||
_session->downloaderTaskFinished(
|
||||
|
@ -618,7 +618,7 @@ void StickersListFooter::paint(
|
|||
return;
|
||||
}
|
||||
|
||||
if (_settingsButtonVisible && !hasOnlyFeaturedSets()) {
|
||||
if (_features.stickersSettings) {
|
||||
paintStickerSettingsIcon(p);
|
||||
}
|
||||
|
||||
|
@ -1012,12 +1012,12 @@ void StickersListFooter::updateSelected() {
|
|||
if (rtl()) x = width() - x;
|
||||
const auto settingsLeft = _iconsLeft - _singleWidth;
|
||||
auto newOver = OverState(SpecialOver::None);
|
||||
if (_settingsButtonVisible
|
||||
if (_features.stickersSettings
|
||||
&& x >= settingsLeft
|
||||
&& x < settingsLeft + _singleWidth
|
||||
&& y >= _iconsTop
|
||||
&& y < _iconsTop + st().footer) {
|
||||
if (!_icons.empty() && !hasOnlyFeaturedSets()) {
|
||||
if (!_icons.empty()) {
|
||||
newOver = SpecialOver::Settings;
|
||||
}
|
||||
} else if (!_icons.empty()) {
|
||||
|
@ -1161,17 +1161,11 @@ void StickersListFooter::refreshSubiconsGeometry() {
|
|||
updateEmojiWidthCallback();
|
||||
}
|
||||
|
||||
bool StickersListFooter::hasOnlyFeaturedSets() const {
|
||||
return (_icons.size() == 1)
|
||||
&& (_icons[0].setId == Data::Stickers::FeaturedSetId);
|
||||
}
|
||||
|
||||
void StickersListFooter::paintStickerSettingsIcon(QPainter &p) const {
|
||||
const auto settingsLeft = _iconsLeft - _singleWidth;
|
||||
st::stickersSettings.paint(
|
||||
st().icons.settings.paint(
|
||||
p,
|
||||
settingsLeft
|
||||
+ (_singleWidth - st::stickersSettings.width()) / 2,
|
||||
(settingsLeft + (_singleWidth - st().icons.settings.width()) / 2),
|
||||
_iconsTop + st::emojiCategoryIconTop,
|
||||
width());
|
||||
}
|
||||
|
@ -1411,22 +1405,22 @@ void StickersListFooter::paintSetIconToCache(
|
|||
using Section = Ui::Emoji::Section;
|
||||
const auto sectionIcon = [&](Section section, bool active) {
|
||||
const auto icons = std::array{
|
||||
&st::emojiRecent,
|
||||
&st::emojiRecentActive,
|
||||
&st::emojiPeople,
|
||||
&st::emojiPeopleActive,
|
||||
&st::emojiNature,
|
||||
&st::emojiNatureActive,
|
||||
&st::emojiFood,
|
||||
&st::emojiFoodActive,
|
||||
&st::emojiActivity,
|
||||
&st::emojiActivityActive,
|
||||
&st::emojiTravel,
|
||||
&st::emojiTravelActive,
|
||||
&st::emojiObjects,
|
||||
&st::emojiObjectsActive,
|
||||
&st::emojiSymbols,
|
||||
&st::emojiSymbolsActive,
|
||||
&st().icons.recent,
|
||||
&st().icons.recentActive,
|
||||
&st().icons.people,
|
||||
&st().icons.peopleActive,
|
||||
&st().icons.nature,
|
||||
&st().icons.natureActive,
|
||||
&st().icons.food,
|
||||
&st().icons.foodActive,
|
||||
&st().icons.activity,
|
||||
&st().icons.activityActive,
|
||||
&st().icons.travel,
|
||||
&st().icons.travelActive,
|
||||
&st().icons.objects,
|
||||
&st().icons.objectsActive,
|
||||
&st().icons.symbols,
|
||||
&st().icons.symbolsActive,
|
||||
};
|
||||
const auto index = int(section) * 2 + (active ? 1 : 0);
|
||||
|
||||
|
@ -1464,15 +1458,8 @@ void StickersListFooter::paintSetIconToCache(
|
|||
} else {
|
||||
paintOne(0, [&] {
|
||||
const auto selected = (info.index == _iconState.selected);
|
||||
if (icon.setId == Data::Stickers::FeaturedSetId) {
|
||||
const auto &stickers = _session->data().stickers();
|
||||
return stickers.featuredSetsUnreadCount()
|
||||
? &st::stickersTrendingUnread
|
||||
: &st::stickersTrending;
|
||||
//} else if (setId == Stickers::FavedSetId) {
|
||||
// return &st::stickersFaved;
|
||||
} else if (icon.setId == AllEmojiSectionSetId()) {
|
||||
return &st::emojiPeople;
|
||||
if (icon.setId == AllEmojiSectionSetId()) {
|
||||
return &st().icons.people;
|
||||
} else if (const auto section = SetIdEmojiSection(icon.setId)) {
|
||||
return sectionIcon(*section, selected);
|
||||
}
|
||||
|
|
|
@ -7,8 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "media/clip/media_clip_reader.h"
|
||||
#include "chat_helpers/compose/compose_features.h"
|
||||
#include "chat_helpers/tabbed_selector.h"
|
||||
#include "media/clip/media_clip_reader.h"
|
||||
#include "mtproto/sender.h"
|
||||
#include "ui/dpr/dpr_image.h"
|
||||
#include "ui/round_rect.h"
|
||||
|
@ -116,8 +117,8 @@ public:
|
|||
not_null<Main::Session*> session;
|
||||
Fn<bool()> paused;
|
||||
not_null<RpWidget*> parent;
|
||||
bool settingsButtonVisible = false;
|
||||
const style::EmojiPan *st = nullptr;
|
||||
ComposeFeatures features;
|
||||
};
|
||||
explicit StickersListFooter(Descriptor &&descriptor);
|
||||
|
||||
|
@ -130,7 +131,6 @@ public:
|
|||
uint64 activeSetId,
|
||||
Fn<std::shared_ptr<Lottie::FrameRenderer>()> renderer,
|
||||
ValidateIconAnimations animations);
|
||||
[[nodiscard]] bool hasOnlyFeaturedSets() const;
|
||||
|
||||
void leaveToChildEvent(QEvent *e, QWidget *child) override;
|
||||
|
||||
|
@ -270,7 +270,7 @@ private:
|
|||
|
||||
const not_null<Main::Session*> _session;
|
||||
const Fn<bool()> _paused;
|
||||
const bool _settingsButtonVisible = false;
|
||||
const ComposeFeatures _features;
|
||||
|
||||
static constexpr auto kVisibleIconsCount = 8;
|
||||
|
||||
|
|
|
@ -184,12 +184,12 @@ StickersListWidget::StickersListWidget(
|
|||
descriptor.paused)
|
||||
, _mode(descriptor.mode)
|
||||
, _show(std::move(descriptor.show))
|
||||
, _features(descriptor.features)
|
||||
, _overBg(st::roundRadiusSmall, st().overBg)
|
||||
, _api(&session().mtp())
|
||||
, _localSetsManager(std::make_unique<LocalStickersManager>(&session()))
|
||||
, _section(Section::Stickers)
|
||||
, _isMasks(_mode == Mode::Masks)
|
||||
, _settingsHidden(descriptor.settingsHidden)
|
||||
, _updateItemsTimer([=] { updateItems(); })
|
||||
, _updateSetsTimer([=] { updateSets(); })
|
||||
, _trendingAddBgOver(
|
||||
|
@ -286,8 +286,8 @@ object_ptr<TabbedSelector::InnerFooter> StickersListWidget::createFooter() {
|
|||
.session = &session(),
|
||||
.paused = footerPaused,
|
||||
.parent = this,
|
||||
.settingsButtonVisible = !_settingsHidden,
|
||||
.st = &st(),
|
||||
.features = _features,
|
||||
});
|
||||
_footer = result;
|
||||
|
||||
|
@ -298,7 +298,7 @@ object_ptr<TabbedSelector::InnerFooter> StickersListWidget::createFooter() {
|
|||
|
||||
_footer->openSettingsRequests(
|
||||
) | rpl::start_with_next([=] {
|
||||
const auto onlyFeatured = _footer->hasOnlyFeaturedSets();
|
||||
const auto onlyFeatured = !_isMasks && _mySets.empty();
|
||||
_show->showBox(Box<StickersBox>(
|
||||
_show,
|
||||
(onlyFeatured
|
||||
|
@ -908,7 +908,7 @@ void StickersListWidget::paintStickers(Painter &p, QRect clip) {
|
|||
auto add = featuredAddRect(info);
|
||||
int checkx = add.left() + (add.width() - st::stickersFeaturedInstalled.width()) / 2;
|
||||
int checky = add.top() + (add.height() - st::stickersFeaturedInstalled.height()) / 2;
|
||||
st::stickersFeaturedInstalled.paint(p, QPoint(checkx, checky), width());
|
||||
st().trendingInstalled.paint(p, QPoint(checkx, checky), width());
|
||||
}
|
||||
if (set.flags & SetFlag::Unread) {
|
||||
widthForTitle -= st::stickersFeaturedUnreadSize + st::stickersFeaturedUnreadSkip;
|
||||
|
@ -921,12 +921,12 @@ void StickersListWidget::paintStickers(Painter &p, QRect clip) {
|
|||
titleWidth = st::stickersTrendingHeaderFont->width(titleText);
|
||||
}
|
||||
p.setFont(st::stickersTrendingHeaderFont);
|
||||
p.setPen(st::stickersTrendingHeaderFg);
|
||||
p.setPen(st().trendingHeaderFg);
|
||||
p.drawTextLeft(st().headerLeft - st().margin.left(), info.top + st::stickersTrendingHeaderTop, width(), titleText, titleWidth);
|
||||
|
||||
if (set.flags & SetFlag::Unread) {
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(st::stickersFeaturedUnreadBg);
|
||||
p.setBrush(st().trendingUnreadFg);
|
||||
|
||||
{
|
||||
PainterHighQualityEnabler hq(p);
|
||||
|
@ -936,7 +936,7 @@ void StickersListWidget::paintStickers(Painter &p, QRect clip) {
|
|||
|
||||
auto statusText = (count > 0) ? tr::lng_stickers_count(tr::now, lt_count, count) : tr::lng_contacts_loading(tr::now);
|
||||
p.setFont(st::stickersTrendingSubheaderFont);
|
||||
p.setPen(st::stickersTrendingSubheaderFg);
|
||||
p.setPen(st().trendingSubheaderFg);
|
||||
p.drawTextLeft(st().headerLeft - st().margin.left(), info.top + st::stickersTrendingSubheaderTop, width(), statusText);
|
||||
|
||||
if (info.rowsTop >= clip.y() + clip.height()) {
|
||||
|
@ -963,13 +963,14 @@ void StickersListWidget::paintStickers(Painter &p, QRect clip) {
|
|||
if (hasRemoveButton(info.section)) {
|
||||
auto remove = removeButtonRect(info);
|
||||
auto selected = selectedButton ? (selectedButton->section == info.section) : false;
|
||||
const auto &removeSt = st().removeSet;
|
||||
if (set.ripple) {
|
||||
set.ripple->paint(p, remove.x() + st::stickerPanRemoveSet.rippleAreaPosition.x(), remove.y() + st::stickerPanRemoveSet.rippleAreaPosition.y(), width());
|
||||
set.ripple->paint(p, remove.x() + removeSt.rippleAreaPosition.x(), remove.y() + removeSt.rippleAreaPosition.y(), width());
|
||||
if (set.ripple->empty()) {
|
||||
set.ripple.reset();
|
||||
}
|
||||
}
|
||||
const auto &icon = selected ? st::stickerPanRemoveSet.iconOver : st::stickerPanRemoveSet.icon;
|
||||
const auto &icon = selected ? removeSt.iconOver : removeSt.icon;
|
||||
icon.paint(
|
||||
p,
|
||||
remove.x() + (remove.width() - icon.width()) / 2,
|
||||
|
@ -983,7 +984,7 @@ void StickersListWidget::paintStickers(Painter &p, QRect clip) {
|
|||
titleWidth = st::stickersTrendingHeaderFont->width(titleText);
|
||||
}
|
||||
p.setFont(st::emojiPanHeaderFont);
|
||||
p.setPen(st::emojiPanHeaderFg);
|
||||
p.setPen(st().headerFg);
|
||||
p.drawTextLeft(st().headerLeft - st().margin.left(), info.top + st().headerTop, width(), titleText, titleWidth);
|
||||
}
|
||||
if (clip.top() + clip.height() <= info.rowsTop) {
|
||||
|
@ -1108,7 +1109,7 @@ int StickersListWidget::megagroupSetInfoLeft() const {
|
|||
}
|
||||
|
||||
void StickersListWidget::paintMegagroupEmptySet(Painter &p, int y, bool buttonSelected) {
|
||||
p.setPen(st::emojiPanHeaderFg);
|
||||
p.setPen(st().headerFg);
|
||||
|
||||
auto infoLeft = megagroupSetInfoLeft();
|
||||
_megagroupSetAbout.drawLeft(p, infoLeft, y, width() - infoLeft, width());
|
||||
|
@ -1483,8 +1484,9 @@ QRect StickersListWidget::removeButtonRect(int index) const {
|
|||
}
|
||||
|
||||
QRect StickersListWidget::removeButtonRect(const SectionInfo &info) const {
|
||||
auto buttonw = st::stickerPanRemoveSet.width;
|
||||
auto buttonh = st::stickerPanRemoveSet.height;
|
||||
const auto &removeSt = st().removeSet;
|
||||
auto buttonw = removeSt.width;
|
||||
auto buttonh = removeSt.height;
|
||||
auto buttonx = stickersRight() - buttonw;
|
||||
auto buttony = info.top + (st().header - buttonh) / 2;
|
||||
return QRect(buttonx, buttony, buttonw, buttonh);
|
||||
|
@ -1561,10 +1563,11 @@ std::unique_ptr<Ui::RippleAnimation> StickersListWidget::createButtonRipple(int
|
|||
std::move(mask),
|
||||
[this, section] { rtlupdate(featuredAddRect(section)); });
|
||||
}
|
||||
auto maskSize = QSize(st::stickerPanRemoveSet.rippleAreaSize, st::stickerPanRemoveSet.rippleAreaSize);
|
||||
const auto &removeSt = st().removeSet;
|
||||
auto maskSize = QSize(removeSt.rippleAreaSize, removeSt.rippleAreaSize);
|
||||
auto mask = Ui::RippleAnimation::EllipseMask(maskSize);
|
||||
return std::make_unique<Ui::RippleAnimation>(
|
||||
st::stickerPanRemoveSet.ripple,
|
||||
removeSt.ripple,
|
||||
std::move(mask),
|
||||
[this, section] { rtlupdate(removeButtonRect(section)); });
|
||||
}
|
||||
|
@ -1575,7 +1578,8 @@ QPoint StickersListWidget::buttonRippleTopLeft(int section) const {
|
|||
if (shownSets()[section].externalLayout) {
|
||||
return myrtlrect(featuredAddRect(section)).topLeft();
|
||||
}
|
||||
return myrtlrect(removeButtonRect(section)).topLeft() + st::stickerPanRemoveSet.rippleAreaPosition;
|
||||
return myrtlrect(removeButtonRect(section)).topLeft()
|
||||
+ st().removeSet.rippleAreaPosition;
|
||||
}
|
||||
|
||||
void StickersListWidget::showStickerSetBox(not_null<DocumentData*> document) {
|
||||
|
@ -1604,9 +1608,7 @@ base::unique_qptr<Ui::PopupMenu> StickersListWidget::fillContextMenu(
|
|||
auto &set = sets[section];
|
||||
Assert(index >= 0 && index < set.stickers.size());
|
||||
|
||||
auto menu = base::make_unique_q<Ui::PopupMenu>(
|
||||
this,
|
||||
st::popupMenuWithIcons);
|
||||
auto menu = base::make_unique_q<Ui::PopupMenu>(this, st().menu);
|
||||
|
||||
const auto document = set.stickers[sticker->index].document;
|
||||
const auto send = [=](Api::SendOptions options) {
|
||||
|
@ -1618,12 +1620,14 @@ base::unique_qptr<Ui::PopupMenu> StickersListWidget::fillContextMenu(
|
|||
: messageSentAnimationInfo(section, index, document),
|
||||
});
|
||||
};
|
||||
const auto icons = &st().icons;
|
||||
SendMenu::FillSendMenu(
|
||||
menu,
|
||||
type,
|
||||
SendMenu::DefaultSilentCallback(send),
|
||||
SendMenu::DefaultScheduleCallback(this, type, send),
|
||||
SendMenu::DefaultWhenOnlineCallback(send));
|
||||
SendMenu::DefaultWhenOnlineCallback(send),
|
||||
icons);
|
||||
|
||||
const auto show = _show;
|
||||
const auto toggleFavedSticker = [=] {
|
||||
|
@ -1638,11 +1642,13 @@ base::unique_qptr<Ui::PopupMenu> StickersListWidget::fillContextMenu(
|
|||
? tr::lng_faved_stickers_remove
|
||||
: tr::lng_faved_stickers_add)(tr::now),
|
||||
toggleFavedSticker,
|
||||
isFaved ? &st::menuIconUnfave : &st::menuIconFave);
|
||||
isFaved ? &icons->menuUnfave : &icons->menuFave);
|
||||
|
||||
menu->addAction(tr::lng_context_pack_info(tr::now), [=] {
|
||||
showStickerSetBox(document);
|
||||
}, &st::menuIconStickers);
|
||||
if (_features.openStickerSets) {
|
||||
menu->addAction(tr::lng_context_pack_info(tr::now), [=] {
|
||||
showStickerSetBox(document);
|
||||
}, &icons->menuStickerSet);
|
||||
}
|
||||
|
||||
if (const auto id = set.id; id == Data::Stickers::RecentSetId) {
|
||||
menu->addAction(tr::lng_recent_stickers_remove(tr::now), [=] {
|
||||
|
@ -1650,7 +1656,7 @@ base::unique_qptr<Ui::PopupMenu> StickersListWidget::fillContextMenu(
|
|||
document,
|
||||
Data::FileOriginStickerSet(id, 0),
|
||||
false);
|
||||
}, &st::menuIconDelete);
|
||||
}, &icons->menuRecentRemove);
|
||||
}
|
||||
return menu;
|
||||
}
|
||||
|
@ -1708,7 +1714,8 @@ void StickersListWidget::mouseReleaseEvent(QMouseEvent *e) {
|
|||
return;
|
||||
}
|
||||
const auto document = set.stickers[sticker->index].document;
|
||||
if (e->modifiers() & Qt::ControlModifier) {
|
||||
if (_features.openStickerSets
|
||||
&& (e->modifiers() & Qt::ControlModifier)) {
|
||||
showStickerSetBox(document);
|
||||
} else {
|
||||
_chosen.fire({
|
||||
|
@ -1859,12 +1866,6 @@ void StickersListWidget::processPanelHideFinished() {
|
|||
if (_footer) {
|
||||
_footer->clearHeavyData();
|
||||
}
|
||||
// Preserve panel state through visibility toggles.
|
||||
//// Reset to the recent stickers section.
|
||||
//if (_section == Section::Featured && (!_footer || !_footer->hasOnlyFeaturedSets())) {
|
||||
// setSection(Section::Stickers);
|
||||
// validateSelectedIcon(ValidateIconAnimations::None);
|
||||
//}
|
||||
}
|
||||
|
||||
void StickersListWidget::setSection(Section section) {
|
||||
|
@ -1994,9 +1995,6 @@ void StickersListWidget::refreshSettingsVisibility() {
|
|||
|
||||
void StickersListWidget::refreshFooterIcons() {
|
||||
refreshIcons(ValidateIconAnimations::None);
|
||||
if (_footer->hasOnlyFeaturedSets() && _section != Section::Featured) {
|
||||
showStickerSet(Data::Stickers::FeaturedSetId);
|
||||
}
|
||||
}
|
||||
|
||||
void StickersListWidget::preloadImages() {
|
||||
|
@ -2064,9 +2062,6 @@ void StickersListWidget::refreshRecent() {
|
|||
if (_section == Section::Stickers) {
|
||||
refreshRecentStickers();
|
||||
}
|
||||
if (_footer && _footer->hasOnlyFeaturedSets() && _section != Section::Featured) {
|
||||
showStickerSet(Data::Stickers::FeaturedSetId);
|
||||
}
|
||||
}
|
||||
|
||||
auto StickersListWidget::collectRecentStickers() -> std::vector<Sticker> {
|
||||
|
@ -2201,7 +2196,7 @@ void StickersListWidget::refreshFavedStickers() {
|
|||
}
|
||||
|
||||
void StickersListWidget::refreshMegagroupStickers(GroupStickersPlace place) {
|
||||
if (!_megagroupSet || _isMasks) {
|
||||
if (!_features.megagroupSet || !_megagroupSet || _isMasks) {
|
||||
return;
|
||||
}
|
||||
auto canEdit = _megagroupSet->canEditStickers();
|
||||
|
@ -2354,10 +2349,12 @@ void StickersListWidget::updateSelected() {
|
|||
newSelected = OverButton{ section };
|
||||
} else if (featuredHasAddButton(section) && myrtlrect(featuredAddRect(info)).contains(p.x(), p.y())) {
|
||||
newSelected = OverButton{ section };
|
||||
} else if (!(sets[section].flags & SetFlag::Special)) {
|
||||
} else if (_features.openStickerSets
|
||||
&& !(sets[section].flags & SetFlag::Special)) {
|
||||
newSelected = OverSet{ section };
|
||||
} else if (sets[section].id == Data::Stickers::MegagroupSetId
|
||||
&& (_megagroupSet->canEditStickers() || !sets[section].stickers.empty())) {
|
||||
} else if ((sets[section].id == Data::Stickers::MegagroupSetId)
|
||||
&& (_megagroupSet->canEditStickers()
|
||||
|| !sets[section].stickers.empty())) {
|
||||
newSelected = OverSet{ section };
|
||||
}
|
||||
} else if (p.y() >= info.rowsTop && p.y() < info.rowsBottom && sx >= 0) {
|
||||
|
@ -2624,10 +2621,12 @@ void StickersListWidget::removeMegagroupSet(bool locally) {
|
|||
close();
|
||||
}),
|
||||
.cancelled = [](Fn<void()> &&close) { close(); },
|
||||
.labelStyle = &st().boxLabel,
|
||||
}));
|
||||
}
|
||||
|
||||
void StickersListWidget::removeSet(uint64 setId) {
|
||||
const auto &st = this->st().boxLabel;
|
||||
if (setId == Data::Stickers::MegagroupSetId) {
|
||||
const auto &sets = shownSets();
|
||||
const auto i = ranges::find(sets, setId, &Set::id);
|
||||
|
@ -2635,7 +2634,7 @@ void StickersListWidget::removeSet(uint64 setId) {
|
|||
const auto removeLocally = i->stickers.empty()
|
||||
|| !_megagroupSet->canEditStickers();
|
||||
removeMegagroupSet(removeLocally);
|
||||
} else if (auto box = MakeConfirmRemoveSetBox(&session(), setId)) {
|
||||
} else if (auto box = MakeConfirmRemoveSetBox(&session(), st, setId)) {
|
||||
checkHideWithBox(std::move(box));
|
||||
}
|
||||
}
|
||||
|
@ -2660,6 +2659,7 @@ StickersListWidget::~StickersListWidget() = default;
|
|||
|
||||
object_ptr<Ui::BoxContent> MakeConfirmRemoveSetBox(
|
||||
not_null<Main::Session*> session,
|
||||
const style::FlatLabel &st,
|
||||
uint64 setId) {
|
||||
const auto &sets = session->data().stickers().sets();
|
||||
const auto it = sets.find(setId);
|
||||
|
@ -2726,6 +2726,7 @@ object_ptr<Ui::BoxContent> MakeConfirmRemoveSetBox(
|
|||
}
|
||||
},
|
||||
.confirmText = tr::lng_stickers_remove_pack_confirm(),
|
||||
.labelStyle = &st,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "chat_helpers/compose/compose_features.h"
|
||||
#include "chat_helpers/tabbed_selector.h"
|
||||
#include "data/stickers/data_stickers.h"
|
||||
#include "ui/round_rect.h"
|
||||
|
@ -50,6 +51,7 @@ enum class Notification;
|
|||
|
||||
namespace style {
|
||||
struct EmojiPan;
|
||||
struct FlatLabel;
|
||||
} // namespace style
|
||||
|
||||
namespace ChatHelpers {
|
||||
|
@ -70,7 +72,7 @@ struct StickersListDescriptor {
|
|||
StickersListMode mode = StickersListMode::Full;
|
||||
Fn<bool()> paused;
|
||||
const style::EmojiPan *st = nullptr;
|
||||
bool settingsHidden = false;
|
||||
ComposeFeatures features;
|
||||
};
|
||||
|
||||
class StickersListWidget final : public TabbedSelector::Inner {
|
||||
|
@ -352,6 +354,7 @@ private:
|
|||
|
||||
const Mode _mode;
|
||||
const std::shared_ptr<Show> _show;
|
||||
const ComposeFeatures _features;
|
||||
Ui::RoundRect _overBg;
|
||||
std::unique_ptr<Ui::TabbedSearch> _search;
|
||||
MTP::Sender _api;
|
||||
|
@ -375,7 +378,6 @@ private:
|
|||
|
||||
Section _section = Section::Stickers;
|
||||
const bool _isMasks;
|
||||
bool _settingsHidden = false;
|
||||
|
||||
base::Timer _updateItemsTimer;
|
||||
base::Timer _updateSetsTimer;
|
||||
|
@ -426,6 +428,7 @@ private:
|
|||
|
||||
[[nodiscard]] object_ptr<Ui::BoxContent> MakeConfirmRemoveSetBox(
|
||||
not_null<Main::Session*> session,
|
||||
const style::FlatLabel &st,
|
||||
uint64 setId);
|
||||
|
||||
} // namespace ChatHelpers
|
||||
|
|
|
@ -240,7 +240,7 @@ void TabbedPanel::paintEvent(QPaintEvent *e) {
|
|||
hideFinished();
|
||||
} else {
|
||||
if (!_cache.isNull()) _cache = QPixmap();
|
||||
Ui::Shadow::paint(p, innerRect(), width(), st::emojiPanAnimation.shadow);
|
||||
Ui::Shadow::paint(p, innerRect(), width(), _selector->st().showAnimation.shadow);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -362,7 +362,11 @@ void TabbedPanel::startShowAnimation() {
|
|||
if (!_a_show.animating()) {
|
||||
auto image = grabForAnimation();
|
||||
|
||||
_showAnimation = std::make_unique<Ui::PanelAnimation>(st::emojiPanAnimation, _dropDown ? Ui::PanelAnimation::Origin::TopRight : Ui::PanelAnimation::Origin::BottomRight);
|
||||
_showAnimation = std::make_unique<Ui::PanelAnimation>(
|
||||
_selector->st().showAnimation,
|
||||
(_dropDown
|
||||
? Ui::PanelAnimation::Origin::TopRight
|
||||
: Ui::PanelAnimation::Origin::BottomRight));
|
||||
auto inner = rect().marginsRemoved(st::emojiPanMargins);
|
||||
_showAnimation->setFinalImage(std::move(image), QRect(inner.topLeft() * cIntRetinaFactor(), inner.size() * cIntRetinaFactor()));
|
||||
_showAnimation->setCornerMasks(Images::CornersMask(st::emojiPanRadius));
|
||||
|
|
|
@ -344,6 +344,7 @@ TabbedSelector::TabbedSelector(
|
|||
TabbedSelectorDescriptor &&descriptor)
|
||||
: RpWidget(parent)
|
||||
, _st(descriptor.st)
|
||||
, _features(descriptor.features)
|
||||
, _show(std::move(descriptor.show))
|
||||
, _level(descriptor.level)
|
||||
, _mode(descriptor.mode)
|
||||
|
@ -377,7 +378,6 @@ TabbedSelector::TabbedSelector(
|
|||
: SelectorTab::Emoji)
|
||||
, _hasEmojiTab(ranges::contains(_tabs, SelectorTab::Emoji, &Tab::type))
|
||||
, _hasStickersTab(ranges::contains(_tabs, SelectorTab::Stickers, &Tab::type))
|
||||
, _stickersSettingsHidden(descriptor.stickersSettingsHidden)
|
||||
, _hasGifsTab(ranges::contains(_tabs, SelectorTab::Gifs, &Tab::type))
|
||||
, _hasMasksTab(ranges::contains(_tabs, SelectorTab::Masks, &Tab::type))
|
||||
, _tabbed(_tabs.size() > 1) {
|
||||
|
@ -487,6 +487,10 @@ TabbedSelector::TabbedSelector(
|
|||
|
||||
TabbedSelector::~TabbedSelector() = default;
|
||||
|
||||
const style::EmojiPan &TabbedSelector::st() const {
|
||||
return _st;
|
||||
}
|
||||
|
||||
Main::Session &TabbedSelector::session() const {
|
||||
return _show->session();
|
||||
}
|
||||
|
@ -511,6 +515,7 @@ TabbedSelector::Tab TabbedSelector::createTab(SelectorTab type, int index) {
|
|||
: EmojiMode::Full),
|
||||
.paused = paused,
|
||||
.st = &_st,
|
||||
.features = _features,
|
||||
});
|
||||
}
|
||||
case SelectorTab::Stickers: {
|
||||
|
@ -521,7 +526,7 @@ TabbedSelector::Tab TabbedSelector::createTab(SelectorTab type, int index) {
|
|||
.mode = StickersMode::Full,
|
||||
.paused = paused,
|
||||
.st = &_st,
|
||||
.settingsHidden = _stickersSettingsHidden,
|
||||
.features = _features,
|
||||
});
|
||||
}
|
||||
case SelectorTab::Gifs: {
|
||||
|
@ -540,6 +545,7 @@ TabbedSelector::Tab TabbedSelector::createTab(SelectorTab type, int index) {
|
|||
.mode = StickersMode::Masks,
|
||||
.paused = paused,
|
||||
.st = &_st,
|
||||
.features = _features,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#pragma once
|
||||
|
||||
#include "api/api_common.h"
|
||||
#include "chat_helpers/compose/compose_features.h"
|
||||
#include "ui/rp_widget.h"
|
||||
#include "ui/effects/animations.h"
|
||||
#include "ui/effects/message_sending_animation_common.h"
|
||||
|
@ -87,7 +88,7 @@ struct TabbedSelectorDescriptor {
|
|||
const style::EmojiPan &st;
|
||||
PauseReason level = {};
|
||||
TabbedSelectorMode mode = TabbedSelectorMode::Full;
|
||||
bool stickersSettingsHidden = false;
|
||||
ComposeFeatures features;
|
||||
};
|
||||
|
||||
[[nodiscard]] std::unique_ptr<Ui::TabbedSearch> MakeSearch(
|
||||
|
@ -117,6 +118,7 @@ public:
|
|||
TabbedSelectorDescriptor &&descriptor);
|
||||
~TabbedSelector();
|
||||
|
||||
[[nodiscard]] const style::EmojiPan &st() const;
|
||||
[[nodiscard]] Main::Session &session() const;
|
||||
[[nodiscard]] PauseReason level() const;
|
||||
|
||||
|
@ -267,6 +269,7 @@ private:
|
|||
not_null<StickersListWidget*> masks() const;
|
||||
|
||||
const style::EmojiPan &_st;
|
||||
const ComposeFeatures _features;
|
||||
const std::shared_ptr<Show> _show;
|
||||
const PauseReason _level = {};
|
||||
|
||||
|
@ -291,7 +294,6 @@ private:
|
|||
|
||||
const bool _hasEmojiTab;
|
||||
const bool _hasStickersTab;
|
||||
const bool _stickersSettingsHidden;
|
||||
const bool _hasGifsTab;
|
||||
const bool _hasMasksTab;
|
||||
const bool _tabbed;
|
||||
|
|
|
@ -1388,7 +1388,7 @@ AutocompleteQuery HistoryWidget::parseMentionHashtagBotCommandQuery() const {
|
|||
const auto result = (isChoosingTheme()
|
||||
|| (_inlineBot && !_inlineLookingUpBot))
|
||||
? AutocompleteQuery()
|
||||
: ParseMentionHashtagBotCommandQuery(_field);
|
||||
: ParseMentionHashtagBotCommandQuery(_field, {});
|
||||
if (result.query.isEmpty()) {
|
||||
return result;
|
||||
} else if (result.query[0] == '#'
|
||||
|
|
|
@ -956,7 +956,7 @@ ComposeControls::ComposeControls(
|
|||
.st = _st.tabbed,
|
||||
.level = Window::GifPauseReason::TabbedPanel,
|
||||
.mode = ChatHelpers::TabbedSelector::Mode::Full,
|
||||
.stickersSettingsHidden = !_features.stickersSettings,
|
||||
.features = _features,
|
||||
}))
|
||||
, _selector(_regularWindow
|
||||
? _regularWindow->tabbedSelector()
|
||||
|
@ -982,7 +982,10 @@ ComposeControls::ComposeControls(
|
|||
_wrap.get(),
|
||||
st::historyBotCommandStart)
|
||||
: nullptr)
|
||||
, _autocomplete(std::make_unique<FieldAutocomplete>(parent, _show))
|
||||
, _autocomplete(std::make_unique<FieldAutocomplete>(
|
||||
parent,
|
||||
_show,
|
||||
&_st.tabbed))
|
||||
, _header(std::make_unique<FieldHeader>(_wrap.get(), _show))
|
||||
, _voiceRecordBar(std::make_unique<VoiceRecordBar>(
|
||||
_wrap.get(),
|
||||
|
@ -1389,7 +1392,7 @@ void ComposeControls::checkAutocomplete() {
|
|||
const auto peer = _history->peer;
|
||||
const auto autocomplete = _isInlineBot
|
||||
? AutocompleteQuery()
|
||||
: ParseMentionHashtagBotCommandQuery(_field);
|
||||
: ParseMentionHashtagBotCommandQuery(_field, _features);
|
||||
if (!autocomplete.query.isEmpty()) {
|
||||
if (autocomplete.query[0] == '#'
|
||||
&& cRecentWriteHashtags().isEmpty()
|
||||
|
@ -1656,7 +1659,11 @@ void ComposeControls::initField() {
|
|||
_parent,
|
||||
_field,
|
||||
_session,
|
||||
{ .suggestCustomEmoji = true, .allowCustomWithoutPremium = allow });
|
||||
{
|
||||
.suggestCustomEmoji = true,
|
||||
.allowCustomWithoutPremium = allow,
|
||||
.st = &_st.suggestions,
|
||||
});
|
||||
_raiseEmojiSuggestions = [=] { suggestions->raise(); };
|
||||
|
||||
const auto rawTextEdit = _field->rawTextEdit().get();
|
||||
|
|
|
@ -7,10 +7,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "base/required.h"
|
||||
#include "api/api_common.h"
|
||||
#include "base/required.h"
|
||||
#include "base/unique_qptr.h"
|
||||
#include "base/timer.h"
|
||||
#include "chat_helpers/compose/compose_features.h"
|
||||
#include "dialogs/dialogs_key.h"
|
||||
#include "history/view/controls/compose_controls_common.h"
|
||||
#include "ui/round_rect.h"
|
||||
|
@ -93,16 +94,6 @@ enum class ComposeControlsMode {
|
|||
Scheduled,
|
||||
};
|
||||
|
||||
struct ComposeControlsFeatures {
|
||||
bool sendAs = true;
|
||||
bool ttlInfo = true;
|
||||
bool botCommandSend = true;
|
||||
bool silentBroadcastToggle = true;
|
||||
bool attachBotsMenu = true;
|
||||
bool inlineBots = true;
|
||||
bool stickersSettings = true;
|
||||
};
|
||||
|
||||
struct ComposeControlsDescriptor {
|
||||
const style::ComposeControls *stOverride = nullptr;
|
||||
std::shared_ptr<ChatHelpers::Show> show;
|
||||
|
@ -111,7 +102,7 @@ struct ComposeControlsDescriptor {
|
|||
SendMenu::Type sendMenuType = {};
|
||||
Window::SessionController *regularWindow = nullptr;
|
||||
rpl::producer<ChatHelpers::FileChosen> stickerOrEmojiChosen;
|
||||
ComposeControlsFeatures features;
|
||||
ChatHelpers::ComposeFeatures features;
|
||||
};
|
||||
|
||||
class ComposeControls final {
|
||||
|
@ -329,7 +320,7 @@ private:
|
|||
void changeFocusedControl();
|
||||
|
||||
const style::ComposeControls &_st;
|
||||
const ComposeControlsFeatures _features;
|
||||
const ChatHelpers::ComposeFeatures _features;
|
||||
const not_null<QWidget*> _parent;
|
||||
const std::shared_ptr<ChatHelpers::Show> _show;
|
||||
const not_null<Main::Session*> _session;
|
||||
|
|
|
@ -321,7 +321,7 @@ void EmojiSelector::createSelector(Type type) {
|
|||
if (isEmoji) {
|
||||
st::userpicBuilderEmojiToggleStickersIcon.paintInCenter(p, r);
|
||||
} else {
|
||||
st::emojiPeople.paintInCenter(p, r);
|
||||
st::defaultEmojiPan.icons.people.paintInCenter(p, r);
|
||||
}
|
||||
}, toggleButton->lifetime());
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "inline_bots/inline_bot_result.h"
|
||||
#include "media/stories/media_stories_controller.h"
|
||||
#include "menu/menu_send.h"
|
||||
#include "styles/style_chat_helpers.h"
|
||||
#include "styles/style_media_view.h"
|
||||
|
||||
namespace Media::Stories {
|
||||
|
@ -41,6 +42,12 @@ ReplyArea::ReplyArea(not_null<Controller*> controller)
|
|||
.silentBroadcastToggle = false,
|
||||
.attachBotsMenu = false,
|
||||
.inlineBots = false,
|
||||
.megagroupSet = false,
|
||||
.stickersSettings = false,
|
||||
.openStickerSets = false,
|
||||
.autocompleteHashtags = false,
|
||||
.autocompleteMentions = false,
|
||||
.autocompleteCommands = false,
|
||||
},
|
||||
}
|
||||
)) {
|
||||
|
@ -52,13 +59,27 @@ ReplyArea::~ReplyArea() {
|
|||
}
|
||||
|
||||
void ReplyArea::initGeometry() {
|
||||
_controller->layoutValue(
|
||||
) | rpl::start_with_next([=](const Layout &layout) {
|
||||
_controls->resizeToWidth(layout.content.width());
|
||||
const auto position = layout.controlsBottomPosition
|
||||
- QPoint(0, _controls->heightCurrent());
|
||||
_controls->move(position.x(), position.y());
|
||||
_controls->setAutocompleteBoundingRect(layout.autocompleteRect);
|
||||
rpl::combine(
|
||||
_controller->layoutValue(),
|
||||
_controls->height()
|
||||
) | rpl::start_with_next([=](const Layout &layout, int height) {
|
||||
const auto content = layout.content;
|
||||
_controls->resizeToWidth(content.width());
|
||||
if (_controls->heightCurrent() == height) {
|
||||
const auto position = layout.controlsBottomPosition
|
||||
- QPoint(0, height);
|
||||
_controls->move(position.x(), position.y());
|
||||
const auto &tabbed = st::storiesComposeControls.tabbed;
|
||||
const auto upper = QRect(
|
||||
content.x(),
|
||||
content.y(),
|
||||
content.width(),
|
||||
(position.y()
|
||||
+ tabbed.autocompleteBottomSkip
|
||||
- content.y()));
|
||||
_controls->setAutocompleteBoundingRect(
|
||||
layout.autocompleteRect.intersected(upper));
|
||||
}
|
||||
}, _lifetime);
|
||||
}
|
||||
|
||||
|
|
|
@ -407,7 +407,7 @@ pipVolumeIcon2Over: icon {{ "player/player_volume_on", mediaviewPipControlsFgOve
|
|||
|
||||
speedSliderDividerSize: size(2px, 8px);
|
||||
|
||||
storiesMaxSize: size(405px, 720px);
|
||||
storiesMaxSize: size(540px, 960px);
|
||||
storiesMaxNameFontSize: 17px;
|
||||
storiesRadius: 8px;
|
||||
storiesControlSize: 64px;
|
||||
|
@ -460,6 +460,53 @@ storiesAttach: IconButton(historyAttach) {
|
|||
}
|
||||
storiesRecordVoice: icon {{ "chat/input_record", storiesComposeGrayIcon }};
|
||||
storiesRecordVoiceOver: icon {{ "chat/input_record", storiesComposeGrayIcon }};
|
||||
storiesRemoveSet: IconButton(stickerPanRemoveSet) {
|
||||
icon: icon {{ "simple_close", storiesComposeGrayIcon }};
|
||||
iconOver: icon {{ "simple_close", storiesComposeGrayIcon }};
|
||||
ripple: RippleAnimation(defaultRippleAnimation) {
|
||||
color: storiesComposeBgOver;
|
||||
}
|
||||
}
|
||||
storiesMenu: Menu(defaultMenu) {
|
||||
itemBg: groupCallMenuBg;
|
||||
itemBgOver: groupCallMenuBgOver;
|
||||
itemFg: groupCallMembersFg;
|
||||
itemFgOver: groupCallMembersFg;
|
||||
itemFgDisabled: groupCallMemberNotJoinedStatus;
|
||||
itemFgShortcut: groupCallMemberNotJoinedStatus;
|
||||
itemFgShortcutOver: groupCallMemberNotJoinedStatus;
|
||||
itemFgShortcutDisabled: groupCallMemberNotJoinedStatus;
|
||||
|
||||
separator: MenuSeparator(defaultMenuSeparator) {
|
||||
fg: groupCallMenuBgOver;
|
||||
}
|
||||
arrow: icon {{ "menu/submenu_arrow", groupCallMemberNotJoinedStatus }};
|
||||
|
||||
ripple: RippleAnimation(defaultRippleAnimation) {
|
||||
color: groupCallMenuBgRipple;
|
||||
}
|
||||
}
|
||||
storiesMenuShadow: Shadow(defaultEmptyShadow) {
|
||||
fallback: groupCallMenuBg;
|
||||
}
|
||||
storiesMenuAnimation: PanelAnimation(defaultPanelAnimation) {
|
||||
fadeBg: groupCallMenuBg;
|
||||
shadow: storiesMenuShadow;
|
||||
}
|
||||
storiesPopupMenu: PopupMenu(defaultPopupMenu) {
|
||||
shadow: storiesMenuShadow;
|
||||
menu: storiesMenu;
|
||||
animation: storiesMenuAnimation;
|
||||
}
|
||||
storiesMenuWithIcons: Menu(storiesMenu) {
|
||||
itemIconPosition: point(15px, 5px);
|
||||
itemPadding: margins(54px, 8px, 17px, 8px);
|
||||
}
|
||||
storiesPopupMenuWithIcons: PopupMenu(storiesPopupMenu) {
|
||||
scrollPadding: margins(0px, 5px, 0px, 5px);
|
||||
menu: storiesMenuWithIcons;
|
||||
}
|
||||
|
||||
storiesComposeControls: ComposeControls(defaultComposeControls) {
|
||||
bg: storiesComposeBg;
|
||||
radius: storiesRadius;
|
||||
|
@ -469,6 +516,7 @@ storiesComposeControls: ComposeControls(defaultComposeControls) {
|
|||
placeholderFg: storiesComposeGrayText;
|
||||
placeholderFgActive: storiesComposeGrayText;
|
||||
placeholderFgError: storiesComposeGrayText;
|
||||
menu: storiesPopupMenu;
|
||||
}
|
||||
send: SendButton(historySend) {
|
||||
inner: IconButton(storiesAttach) {
|
||||
|
@ -489,10 +537,30 @@ storiesComposeControls: ComposeControls(defaultComposeControls) {
|
|||
lineFg: storiesComposeGrayIcon;
|
||||
lineFgOver: storiesComposeGrayIcon;
|
||||
}
|
||||
tabbed: EmojiPan(defaultEmojiPan) {
|
||||
suggestions: EmojiSuggestions(defaultEmojiSuggestions) {
|
||||
dropdown: InnerDropdown(emojiSuggestionsDropdown) {
|
||||
animation: PanelAnimation(defaultPanelAnimation) {
|
||||
fadeBg: storiesComposeBg;
|
||||
}
|
||||
bg: storiesComposeBg;
|
||||
}
|
||||
bg: storiesComposeBg;
|
||||
overBg: storiesComposeBgOver;
|
||||
expandBg: storiesComposeGrayText;
|
||||
textFg: storiesComposeWhiteText;
|
||||
fadeLeft: icon {{ "fade_horizontal-flip_horizontal", storiesComposeBg }};
|
||||
fadeRight: icon {{ "fade_horizontal", storiesComposeBg }};
|
||||
}
|
||||
tabbed: EmojiPan(defaultEmojiPan) {
|
||||
showAnimation: PanelAnimation(emojiPanAnimation) {
|
||||
fadeBg: storiesComposeBg;
|
||||
}
|
||||
bg: storiesComposeBg;
|
||||
headerFg: storiesComposeGrayText;
|
||||
trendingHeaderFg: storiesComposeWhiteText;
|
||||
trendingSubheaderFg: storiesComposeGrayText;
|
||||
trendingUnreadFg: storiesComposeBlue;
|
||||
trendingInstalled: icon {{ "chat/input_save", storiesComposeBlue }};
|
||||
overBg: storiesComposeBgOver;
|
||||
pathBg: storiesComposeBgRipple;
|
||||
pathFg: storiesComposeBgOver;
|
||||
textFg: storiesComposeWhiteText;
|
||||
|
@ -500,6 +568,7 @@ storiesComposeControls: ComposeControls(defaultComposeControls) {
|
|||
categoriesBgOver: storiesComposeBgOver;
|
||||
fadeLeft: icon {{ "fade_horizontal-flip_horizontal", storiesComposeBg }};
|
||||
fadeRight: icon {{ "fade_horizontal", storiesComposeBg }};
|
||||
menu: storiesPopupMenuWithIcons;
|
||||
tabs: SettingsSlider(emojiTabs) {
|
||||
barFgActive: storiesComposeBlue;
|
||||
labelFg: storiesComposeGrayText;
|
||||
|
@ -536,5 +605,40 @@ storiesComposeControls: ComposeControls(defaultComposeControls) {
|
|||
ripple: emptyRippleAnimation;
|
||||
}
|
||||
}
|
||||
removeSet: storiesRemoveSet;
|
||||
boxLabel: FlatLabel(boxLabel) {
|
||||
textFg: groupCallMembersFg;
|
||||
}
|
||||
icons: ComposeIcons {
|
||||
settings: icon {{ "emoji/emoji_settings", storiesComposeGrayIcon }};
|
||||
|
||||
recent: icon {{ "emoji/emoji_recent", storiesComposeGrayIcon }};
|
||||
recentActive: icon {{ "emoji/emoji_recent", storiesComposeWhiteText }};
|
||||
people: icon {{ "emoji/emoji_smile", storiesComposeGrayIcon }};
|
||||
peopleActive: icon {{ "emoji/emoji_smile", storiesComposeWhiteText }};
|
||||
nature: icon {{ "emoji/emoji_nature", storiesComposeGrayIcon }};
|
||||
natureActive: icon {{ "emoji/emoji_nature", storiesComposeWhiteText }};
|
||||
food: icon {{ "emoji/emoji_food", storiesComposeGrayIcon }};
|
||||
foodActive: icon {{ "emoji/emoji_food", storiesComposeWhiteText }};
|
||||
activity: icon {{ "emoji/emoji_activities", storiesComposeGrayIcon }};
|
||||
activityActive: icon {{ "emoji/emoji_activities", storiesComposeWhiteText }};
|
||||
travel: icon {{ "emoji/emoji_travel", storiesComposeGrayIcon }};
|
||||
travelActive: icon {{ "emoji/emoji_travel", storiesComposeWhiteText }};
|
||||
objects: icon {{ "emoji/emoji_objects", storiesComposeGrayIcon }};
|
||||
objectsActive: icon {{ "emoji/emoji_objects", storiesComposeWhiteText }};
|
||||
symbols: icon {{ "emoji/emoji_love", storiesComposeGrayIcon }};
|
||||
symbolsActive: icon {{ "emoji/emoji_love", storiesComposeWhiteText }};
|
||||
|
||||
menuFave: icon {{ "menu/favorite", storiesComposeWhiteText }};
|
||||
menuUnfave: icon {{ "menu/unfavorite", storiesComposeWhiteText }};
|
||||
menuStickerSet: icon {{ "menu/stickers", storiesComposeWhiteText }};
|
||||
menuRecentRemove: icon {{ "menu/delete", storiesComposeWhiteText }};
|
||||
menuGifAdd: icon {{ "menu/gif", storiesComposeWhiteText }};
|
||||
menuGifRemove: icon {{ "menu/delete", storiesComposeWhiteText }};
|
||||
menuMute: icon {{ "menu/mute", storiesComposeWhiteText }};
|
||||
menuSchedule: icon {{ "menu/calendar", storiesComposeWhiteText }};
|
||||
menuWhenOnline: icon {{ "menu/send_when_online", storiesComposeWhiteText }};
|
||||
}
|
||||
autocompleteBottomSkip: 10px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "history/history.h"
|
||||
#include "history/history_unread_things.h"
|
||||
#include "apiwrap.h"
|
||||
#include "styles/style_chat_helpers.h"
|
||||
#include "styles/style_menu_icons.h"
|
||||
|
||||
#include <QtWidgets/QApplication>
|
||||
|
@ -56,10 +57,14 @@ FillMenuResult FillSendMenu(
|
|||
Type type,
|
||||
Fn<void()> silent,
|
||||
Fn<void()> schedule,
|
||||
Fn<void()> whenOnline) {
|
||||
Fn<void()> whenOnline,
|
||||
const style::ComposeIcons *iconsOverride) {
|
||||
if (!silent && !schedule) {
|
||||
return FillMenuResult::None;
|
||||
}
|
||||
const auto &icons = iconsOverride
|
||||
? *iconsOverride
|
||||
: st::defaultComposeIcons;
|
||||
const auto now = type;
|
||||
if (now == Type::Disabled
|
||||
|| (!silent && now == Type::SilentOnly)) {
|
||||
|
@ -70,7 +75,7 @@ FillMenuResult FillSendMenu(
|
|||
menu->addAction(
|
||||
tr::lng_send_silent_message(tr::now),
|
||||
silent,
|
||||
&st::menuIconMute);
|
||||
&icons.menuMute);
|
||||
}
|
||||
if (schedule && now != Type::SilentOnly) {
|
||||
menu->addAction(
|
||||
|
@ -78,13 +83,13 @@ FillMenuResult FillSendMenu(
|
|||
? tr::lng_reminder_message(tr::now)
|
||||
: tr::lng_schedule_message(tr::now)),
|
||||
schedule,
|
||||
&st::menuIconSchedule);
|
||||
&icons.menuSchedule);
|
||||
}
|
||||
if (whenOnline && now == Type::ScheduledToUser) {
|
||||
menu->addAction(
|
||||
tr::lng_scheduled_send_until_online(tr::now),
|
||||
whenOnline,
|
||||
&st::menuIconWhenOnline);
|
||||
&icons.menuWhenOnline);
|
||||
}
|
||||
return FillMenuResult::Success;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
namespace style {
|
||||
struct ComposeIcons;
|
||||
} // namespace style
|
||||
|
||||
namespace Api {
|
||||
struct SendOptions;
|
||||
} // namespace Api
|
||||
|
@ -47,7 +51,8 @@ FillMenuResult FillSendMenu(
|
|||
Type type,
|
||||
Fn<void()> silent,
|
||||
Fn<void()> schedule,
|
||||
Fn<void()> whenOnline);
|
||||
Fn<void()> whenOnline,
|
||||
const style::ComposeIcons *iconsOverride = nullptr);
|
||||
|
||||
void SetupMenuAndShortcuts(
|
||||
not_null<Ui::RpWidget*> button,
|
||||
|
|