Replace some std::shared_ptr with std::unique_ptr.

This commit is contained in:
John Preston 2017-12-18 14:38:14 +04:00
parent 14034c255e
commit 37b018257e
16 changed files with 421 additions and 248 deletions

View File

@ -108,16 +108,18 @@ void BotKeyboard::leaveEventHook(QEvent *e) {
} }
bool BotKeyboard::moderateKeyActivate(int key) { bool BotKeyboard::moderateKeyActivate(int key) {
if (auto item = App::histItemById(_wasForMsgId)) { if (const auto item = App::histItemById(_wasForMsgId)) {
if (auto markup = item->Get<HistoryMessageReplyMarkup>()) { if (const auto markup = item->Get<HistoryMessageReplyMarkup>()) {
if (key >= Qt::Key_1 && key <= Qt::Key_9) { if (key >= Qt::Key_1 && key <= Qt::Key_9) {
int index = (key - Qt::Key_1); const auto index = int(key - Qt::Key_1);
if (!markup->rows.isEmpty() && index >= 0 && index < markup->rows.front().size()) { if (!markup->rows.empty()
&& index >= 0
&& index < int(markup->rows.front().size())) {
App::activateBotCommand(item, 0, index); App::activateBotCommand(item, 0, index);
return true; return true;
} }
} else if (key == Qt::Key_Q) { } else if (key == Qt::Key_Q) {
if (auto user = item->history()->peer->asUser()) { if (const auto user = item->history()->peer->asUser()) {
if (user->botInfo && item->from() == user) { if (user->botInfo && item->from() == user) {
App::sendBotCommand(user, user, qsl("/translate")); App::sendBotCommand(user, user, qsl("/translate"));
return true; return true;
@ -163,8 +165,10 @@ bool BotKeyboard::updateMarkup(HistoryItem *to, bool force) {
_impl = nullptr; _impl = nullptr;
if (auto markup = to->Get<HistoryMessageReplyMarkup>()) { if (auto markup = to->Get<HistoryMessageReplyMarkup>()) {
if (!markup->rows.isEmpty()) { if (!markup->rows.empty()) {
_impl.reset(new ReplyKeyboard(to, std::make_unique<Style>(this, *_st))); _impl = std::make_unique<ReplyKeyboard>(
to,
std::make_unique<Style>(this, *_st));
} }
} }

View File

@ -113,6 +113,23 @@ private:
}; };
StickersListWidget::Set::Set(
uint64 id,
MTPDstickerSet::Flags flags,
const QString &title,
int hoversSize,
const Stickers::Pack &pack)
: id(id)
, flags(flags)
, title(title)
, pack(pack) {
}
StickersListWidget::Set::Set(Set &&other) = default;
StickersListWidget::Set &StickersListWidget::Set::operator=(
Set &&other) = default;
StickersListWidget::Set::~Set() = default;
StickersListWidget::Footer::Footer(not_null<StickersListWidget*> parent) : InnerFooter(parent) StickersListWidget::Footer::Footer(not_null<StickersListWidget*> parent) : InnerFooter(parent)
, _pan(parent) , _pan(parent)
, _a_icons(animation(this, &Footer::step_icons)) { , _a_icons(animation(this, &Footer::step_icons)) {
@ -605,10 +622,12 @@ int StickersListWidget::countDesiredHeight(int newWidth) {
auto minimalLastHeight = (visibleHeight - st::stickerPanPadding); auto minimalLastHeight = (visibleHeight - st::stickerPanPadding);
auto countResult = [this, minimalLastHeight] { auto countResult = [this, minimalLastHeight] {
if (_section == Section::Featured) { if (_section == Section::Featured) {
return st::stickerPanPadding + shownSets().size() * featuredRowHeight(); return st::stickerPanPadding
+ int(shownSets().size()) * featuredRowHeight();
} else if (!shownSets().empty()) { } else if (!shownSets().empty()) {
auto info = sectionInfo(shownSets().size() - 1); const auto info = sectionInfo(shownSets().size() - 1);
return info.top + qMax(info.rowsBottom - info.top, minimalLastHeight); return info.top
+ qMax(info.rowsBottom - info.top, minimalLastHeight);
} }
return 0; return 0;
}; };
@ -679,7 +698,7 @@ void StickersListWidget::paintFeaturedStickers(Painter &p, QRect clip) {
auto tilly = st::stickerPanPadding; auto tilly = st::stickerPanPadding;
auto ms = getms(); auto ms = getms();
for (auto c = 0, l = sets.size(); c != l; ++c) { for (auto c = 0, l = int(sets.size()); c != l; ++c) {
auto y = tilly; auto y = tilly;
auto &set = sets[c]; auto &set = sets[c];
tilly = y + featuredRowHeight(); tilly = y + featuredRowHeight();
@ -1005,18 +1024,18 @@ QRect StickersListWidget::megagroupSetButtonRectFinal() const {
return result; return result;
} }
std::shared_ptr<Ui::RippleAnimation> StickersListWidget::createButtonRipple(int section) { std::unique_ptr<Ui::RippleAnimation> StickersListWidget::createButtonRipple(int section) {
if (_section == Section::Featured) { if (_section == Section::Featured) {
auto maskSize = QSize(_addWidth - st::stickersTrendingAdd.width, st::stickersTrendingAdd.height); auto maskSize = QSize(_addWidth - st::stickersTrendingAdd.width, st::stickersTrendingAdd.height);
auto mask = Ui::RippleAnimation::roundRectMask(maskSize, st::buttonRadius); auto mask = Ui::RippleAnimation::roundRectMask(maskSize, st::buttonRadius);
return std::make_shared<Ui::RippleAnimation>( return std::make_unique<Ui::RippleAnimation>(
st::stickersTrendingAdd.ripple, st::stickersTrendingAdd.ripple,
std::move(mask), std::move(mask),
[this, section] { rtlupdate(featuredAddRect(section)); }); [this, section] { rtlupdate(featuredAddRect(section)); });
} }
auto maskSize = QSize(st::stickerPanRemoveSet.rippleAreaSize, st::stickerPanRemoveSet.rippleAreaSize); auto maskSize = QSize(st::stickerPanRemoveSet.rippleAreaSize, st::stickerPanRemoveSet.rippleAreaSize);
auto mask = Ui::RippleAnimation::ellipseMask(maskSize); auto mask = Ui::RippleAnimation::ellipseMask(maskSize);
return std::make_shared<Ui::RippleAnimation>( return std::make_unique<Ui::RippleAnimation>(
st::stickerPanRemoveSet.ripple, st::stickerPanRemoveSet.ripple,
std::move(mask), std::move(mask),
[this, section] { rtlupdate(removeButtonRect(section)); }); [this, section] { rtlupdate(removeButtonRect(section)); });
@ -1085,7 +1104,9 @@ void StickersListWidget::mouseReleaseEvent(QMouseEvent *e) {
} }
void StickersListWidget::removeRecentSticker(int section, int index) { void StickersListWidget::removeRecentSticker(int section, int index) {
if (_section != Section::Stickers || section >= _mySets.size() || _mySets[section].id != Stickers::RecentSetId) { if ((_section != Section::Stickers)
|| (section >= int(_mySets.size()))
|| (_mySets[section].id != Stickers::RecentSetId)) {
return; return;
} }
@ -1124,7 +1145,9 @@ void StickersListWidget::removeRecentSticker(int section, int index) {
} }
void StickersListWidget::removeFavedSticker(int section, int index) { void StickersListWidget::removeFavedSticker(int section, int index) {
if (_section != Section::Stickers || section >= _mySets.size() || _mySets[section].id != Stickers::FavedSetId) { if ((_section != Section::Stickers)
|| (section >= int(_mySets.size()))
|| (_mySets[section].id != Stickers::FavedSetId)) {
return; return;
} }
@ -1231,8 +1254,7 @@ void StickersListWidget::refreshStickers() {
} }
void StickersListWidget::refreshSettingsVisibility() { void StickersListWidget::refreshSettingsVisibility() {
auto visible = (_section == Section::Stickers) const auto visible = (_section == Section::Stickers) && _mySets.empty();
&& _mySets.isEmpty();
_settings->setVisible(visible); _settings->setVisible(visible);
} }
@ -1253,7 +1275,7 @@ void StickersListWidget::preloadImages() {
for (int j = 0; j != count; ++j) { for (int j = 0; j != count; ++j) {
if (++k > _columnCount * (_columnCount + 1)) break; if (++k > _columnCount * (_columnCount + 1)) break;
auto sticker = sets.at(i).pack.at(j); auto sticker = sets[i].pack.at(j);
if (!sticker || !sticker->sticker()) continue; if (!sticker || !sticker->sticker()) continue;
bool goodThumb = !sticker->thumb->isNull() && ((sticker->thumb->width() >= 128) || (sticker->thumb->height() >= 128)); bool goodThumb = !sticker->thumb->isNull() && ((sticker->thumb->width() >= 128) || (sticker->thumb->height() >= 128));
@ -1274,10 +1296,15 @@ uint64 StickersListWidget::currentSet(int yOffset) const {
if (_section == Section::Featured) { if (_section == Section::Featured) {
return Stickers::FeaturedSetId; return Stickers::FeaturedSetId;
} }
return _mySets.isEmpty() ? Stickers::RecentSetId : _mySets[sectionInfoByOffset(yOffset).section].id; return _mySets.empty()
? Stickers::RecentSetId
: _mySets[sectionInfoByOffset(yOffset).section].id;
} }
void StickersListWidget::appendSet(Sets &to, uint64 setId, AppendSkip skip) { void StickersListWidget::appendSet(
std::vector<Set> &to,
uint64 setId,
AppendSkip skip) {
auto &sets = Auth().data().stickerSets(); auto &sets = Auth().data().stickerSets();
auto it = sets.constFind(setId); auto it = sets.constFind(setId);
if (it == sets.cend() || it->stickers.isEmpty()) return; if (it == sets.cend() || it->stickers.isEmpty()) return;
@ -1425,7 +1452,7 @@ void StickersListWidget::refreshMegagroupStickers(GroupStickersPlace place) {
void StickersListWidget::fillIcons(QList<StickerIcon> &icons) { void StickersListWidget::fillIcons(QList<StickerIcon> &icons) {
icons.clear(); icons.clear();
icons.reserve(_mySets.size() + 1); icons.reserve(_mySets.size() + 1);
if (Auth().data().featuredStickerSetsUnreadCount() && !_featuredSets.isEmpty()) { if (Auth().data().featuredStickerSetsUnreadCount() && !_featuredSets.empty()) {
icons.push_back(StickerIcon(Stickers::FeaturedSetId)); icons.push_back(StickerIcon(Stickers::FeaturedSetId));
} }
@ -1459,7 +1486,8 @@ void StickersListWidget::fillIcons(QList<StickerIcon> &icons) {
icons.push_back(StickerIcon(_mySets[i].id, s, pixw, pixh)); icons.push_back(StickerIcon(_mySets[i].id, s, pixw, pixh));
} }
if (!Auth().data().featuredStickerSetsUnreadCount() && !_featuredSets.isEmpty()) { if (!Auth().data().featuredStickerSetsUnreadCount()
&& !_featuredSets.empty()) {
icons.push_back(StickerIcon(Stickers::FeaturedSetId)); icons.push_back(StickerIcon(Stickers::FeaturedSetId));
} }
} }

View File

@ -138,15 +138,22 @@ private:
}; };
struct Set { struct Set {
Set(uint64 id, MTPDstickerSet::Flags flags, const QString &title, int32 hoversSize, const Stickers::Pack &pack = Stickers::Pack()) : id(id), flags(flags), title(title), pack(pack) { Set(
} uint64 id,
MTPDstickerSet::Flags flags,
const QString &title,
int hoversSize,
const Stickers::Pack &pack = Stickers::Pack());
Set(Set &&other);
Set &operator=(Set &&other);
~Set();
uint64 id; uint64 id;
MTPDstickerSet::Flags flags; MTPDstickerSet::Flags flags;
QString title; QString title;
Stickers::Pack pack; Stickers::Pack pack;
std::shared_ptr<Ui::RippleAnimation> ripple; std::unique_ptr<Ui::RippleAnimation> ripple;
}; };
using Sets = QList<Set>;
template <typename Callback> template <typename Callback>
bool enumerateSections(Callback callback) const; bool enumerateSections(Callback callback) const;
@ -172,7 +179,7 @@ private:
void updateSelected(); void updateSelected();
void setSelected(OverState newSelected); void setSelected(OverState newSelected);
void setPressed(OverState newPressed); void setPressed(OverState newPressed);
std::shared_ptr<Ui::RippleAnimation> createButtonRipple(int section); std::unique_ptr<Ui::RippleAnimation> createButtonRipple(int section);
QPoint buttonRippleTopLeft(int section) const; QPoint buttonRippleTopLeft(int section) const;
enum class ValidateIconAnimations { enum class ValidateIconAnimations {
@ -182,10 +189,10 @@ private:
}; };
void validateSelectedIcon(ValidateIconAnimations animations); void validateSelectedIcon(ValidateIconAnimations animations);
Sets &shownSets() { std::vector<Set> &shownSets() {
return (_section == Section::Featured) ? _featuredSets : _mySets; return (_section == Section::Featured) ? _featuredSets : _mySets;
} }
const Sets &shownSets() const { const std::vector<Set> &shownSets() const {
return (_section == Section::Featured) ? _featuredSets : _mySets; return (_section == Section::Featured) ? _featuredSets : _mySets;
} }
int featuredRowHeight() const; int featuredRowHeight() const;
@ -210,7 +217,10 @@ private:
Archived, Archived,
Installed, Installed,
}; };
void appendSet(Sets &to, uint64 setId, AppendSkip skip = AppendSkip::None); void appendSet(
std::vector<Set> &to,
uint64 setId,
AppendSkip skip = AppendSkip::None);
void selectEmoji(EmojiPtr emoji); void selectEmoji(EmojiPtr emoji);
int stickersLeft() const; int stickersLeft() const;
@ -222,10 +232,10 @@ private:
void refreshFooterIcons(); void refreshFooterIcons();
ChannelData *_megagroupSet = nullptr; ChannelData *_megagroupSet = nullptr;
Sets _mySets; std::vector<Set> _mySets;
Sets _featuredSets; std::vector<Set> _featuredSets;
OrderedSet<uint64> _installedLocallySets; base::flat_set<uint64> _installedLocallySets;
QList<bool> _custom; std::vector<bool> _custom;
base::flat_set<not_null<DocumentData*>> _favedStickersMap; base::flat_set<not_null<DocumentData*>> _favedStickersMap;
Section _section = Section::Stickers; Section _section = Section::Stickers;

View File

@ -97,7 +97,6 @@ private:
QString _originalUrl, _readable; QString _originalUrl, _readable;
}; };
using TextClickHandlerPtr = std::shared_ptr<TextClickHandler>;
class HiddenUrlClickHandler : public UrlClickHandler { class HiddenUrlClickHandler : public UrlClickHandler {
public: public:

View File

@ -128,33 +128,43 @@ QString ReplyMarkupClickHandler::buttonText() const {
return QString(); return QString();
} }
ReplyKeyboard::ReplyKeyboard(const HistoryItem *item, StylePtr &&s) ReplyKeyboard::Button::Button() = default;
: _item(item) ReplyKeyboard::Button::Button(Button &&other) = default;
, _a_selected(animation(this, &ReplyKeyboard::step_selected)) ReplyKeyboard::Button &ReplyKeyboard::Button::operator=(
, _st(std::move(s)) { Button &&other) = default;
if (auto markup = item->Get<HistoryMessageReplyMarkup>()) { ReplyKeyboard::Button::~Button() = default;
ReplyKeyboard::ReplyKeyboard(
not_null<const HistoryItem*> item,
std::unique_ptr<Style> &&s)
: _item(item)
, _a_selected(animation(this, &ReplyKeyboard::step_selected))
, _st(std::move(s)) {
if (const auto markup = _item->Get<HistoryMessageReplyMarkup>()) {
_rows.reserve(markup->rows.size()); _rows.reserve(markup->rows.size());
for (int i = 0, l = markup->rows.size(); i != l; ++i) { for (auto i = 0, l = int(markup->rows.size()); i != l; ++i) {
auto &row = markup->rows.at(i); auto &row = markup->rows.at(i);
int s = row.size(); int s = row.size();
ButtonRow newRow(s, Button()); auto newRow = std::vector<Button>();
newRow.reserve(s);
for (int j = 0; j != s; ++j) { for (int j = 0; j != s; ++j) {
auto &button = newRow[j]; auto button = Button();
auto str = row.at(j).text; auto str = row.at(j).text;
button.type = row.at(j).type; button.type = row.at(j).type;
button.link = std::make_shared<ReplyMarkupClickHandler>(item, i, j); button.link = std::make_shared<ReplyMarkupClickHandler>(item, i, j);
button.text.setText(_st->textStyle(), TextUtilities::SingleLine(str), _textPlainOptions); button.text.setText(_st->textStyle(), TextUtilities::SingleLine(str), _textPlainOptions);
button.characters = str.isEmpty() ? 1 : str.size(); button.characters = str.isEmpty() ? 1 : str.size();
newRow.push_back(std::move(button));
} }
_rows.push_back(newRow); _rows.push_back(std::move(newRow));
} }
} }
} }
void ReplyKeyboard::updateMessageId() { void ReplyKeyboard::updateMessageId() {
auto msgId = _item->fullId(); const auto msgId = _item->fullId();
for_const (auto &row, _rows) { for (const auto &row : _rows) {
for_const (auto &button, row) { for (const auto &button : row) {
button.link->setMessageId(msgId); button.link->setMessageId(msgId);
} }
} }
@ -165,7 +175,10 @@ void ReplyKeyboard::resize(int width, int height) {
_width = width; _width = width;
auto markup = _item->Get<HistoryMessageReplyMarkup>(); auto markup = _item->Get<HistoryMessageReplyMarkup>();
float64 y = 0, buttonHeight = _rows.isEmpty() ? _st->buttonHeight() : (float64(height + _st->buttonSkip()) / _rows.size()); auto y = 0.;
auto buttonHeight = _rows.empty()
? float64(_st->buttonHeight())
: (float64(height + _st->buttonSkip()) / _rows.size());
for (auto &row : _rows) { for (auto &row : _rows) {
int s = row.size(); int s = row.size();
@ -228,24 +241,30 @@ bool ReplyKeyboard::isEnoughSpace(int width, const style::BotKeyboardButton &st)
return true; return true;
} }
void ReplyKeyboard::setStyle(StylePtr &&st) { void ReplyKeyboard::setStyle(std::unique_ptr<Style> &&st) {
_st = std::move(st); _st = std::move(st);
} }
int ReplyKeyboard::naturalWidth() const { int ReplyKeyboard::naturalWidth() const {
auto result = 0; auto result = 0;
for_const (auto &row, _rows) { for (const auto &row : _rows) {
auto maxMinButtonWidth = 0; auto maxMinButtonWidth = 0;
for_const (auto &button, row) { for (const auto &button : row) {
accumulate_max(maxMinButtonWidth, _st->minButtonWidth(button.type)); accumulate_max(
maxMinButtonWidth,
_st->minButtonWidth(button.type));
} }
auto rowMaxButtonWidth = 0; auto rowMaxButtonWidth = 0;
for_const (auto &button, row) { for (const auto &button : row) {
accumulate_max(rowMaxButtonWidth, qMax(button.text.maxWidth(), 1) + maxMinButtonWidth); accumulate_max(
rowMaxButtonWidth,
qMax(button.text.maxWidth(), 1) + maxMinButtonWidth);
} }
auto rowSize = row.size(); const auto rowSize = int(row.size());
accumulate_max(result, rowSize * rowMaxButtonWidth + (rowSize - 1) * _st->buttonSkip()); accumulate_max(
result,
rowSize * rowMaxButtonWidth + (rowSize - 1) * _st->buttonSkip());
} }
return result; return result;
} }
@ -323,8 +342,13 @@ void ReplyKeyboard::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pr
auto &button = _rows[coords.i][coords.j]; auto &button = _rows[coords.i][coords.j];
if (pressed) { if (pressed) {
if (!button.ripple) { if (!button.ripple) {
auto mask = Ui::RippleAnimation::roundRectMask(button.rect.size(), _st->buttonRadius()); auto mask = Ui::RippleAnimation::roundRectMask(
button.ripple = std::make_shared<Ui::RippleAnimation>(_st->_st->ripple, std::move(mask), [this] { _st->repaint(_item); }); button.rect.size(),
_st->buttonRadius());
button.ripple = std::make_unique<Ui::RippleAnimation>(
_st->_st->ripple,
std::move(mask),
[this] { _st->repaint(_item); });
} }
button.ripple->add(_savedCoords - button.rect.topLeft()); button.ripple->add(_savedCoords - button.rect.topLeft());
} else { } else {
@ -339,13 +363,13 @@ void ReplyKeyboard::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pr
} }
void ReplyKeyboard::startAnimation(int i, int j, int direction) { void ReplyKeyboard::startAnimation(int i, int j, int direction) {
auto notStarted = _animations.isEmpty(); auto notStarted = _animations.empty();
int indexForAnimation = (i * MatrixRowShift + j + 1) * direction; int indexForAnimation = (i * MatrixRowShift + j + 1) * direction;
_animations.remove(-indexForAnimation); _animations.remove(-indexForAnimation);
if (!_animations.contains(indexForAnimation)) { if (!_animations.contains(indexForAnimation)) {
_animations.insert(indexForAnimation, getms()); _animations.emplace(indexForAnimation, getms());
} }
if (notStarted && !_a_selected.animating()) { if (notStarted && !_a_selected.animating()) {
@ -354,26 +378,30 @@ void ReplyKeyboard::startAnimation(int i, int j, int direction) {
} }
void ReplyKeyboard::step_selected(TimeMs ms, bool timer) { void ReplyKeyboard::step_selected(TimeMs ms, bool timer) {
for (Animations::iterator i = _animations.begin(); i != _animations.end();) { for (auto i = _animations.begin(); i != _animations.end();) {
int index = qAbs(i.key()) - 1, row = (index / MatrixRowShift), col = index % MatrixRowShift; const auto index = std::abs(i->first) - 1;
float64 dt = float64(ms - i.value()) / st::botKbDuration; const auto row = (index / MatrixRowShift);
const auto col = index % MatrixRowShift;
const auto dt = float64(ms - i->second) / st::botKbDuration;
if (dt >= 1) { if (dt >= 1) {
_rows[row][col].howMuchOver = (i.key() > 0) ? 1 : 0; _rows[row][col].howMuchOver = (i->first > 0) ? 1 : 0;
i = _animations.erase(i); i = _animations.erase(i);
} else { } else {
_rows[row][col].howMuchOver = (i.key() > 0) ? dt : (1 - dt); _rows[row][col].howMuchOver = (i->first > 0) ? dt : (1 - dt);
++i; ++i;
} }
} }
if (timer) _st->repaint(_item); if (timer) _st->repaint(_item);
if (_animations.isEmpty()) { if (_animations.empty()) {
_a_selected.stop(); _a_selected.stop();
} }
} }
void ReplyKeyboard::clearSelection() { void ReplyKeyboard::clearSelection() {
for (auto i = _animations.cbegin(), e = _animations.cend(); i != e; ++i) { for (const auto [relativeIndex, time] : _animations) {
int index = qAbs(i.key()) - 1, row = (index / MatrixRowShift), col = index % MatrixRowShift; const auto index = std::abs(relativeIndex) - 1;
const auto row = (index / MatrixRowShift);
const auto col = index % MatrixRowShift;
_rows[row][col].howMuchOver = 0; _rows[row][col].howMuchOver = 0;
} }
_animations.clear(); _animations.clear();
@ -435,7 +463,7 @@ void HistoryMessageReplyMarkup::createFromButtonRows(const QVector<MTPKeyboardBu
auto &r = row.c_keyboardButtonRow(); auto &r = row.c_keyboardButtonRow();
auto &b = r.vbuttons.v; auto &b = r.vbuttons.v;
if (!b.isEmpty()) { if (!b.isEmpty()) {
ButtonRow buttonRow; auto buttonRow = std::vector<Button>();
buttonRow.reserve(b.size()); buttonRow.reserve(b.size());
for_const (auto &button, b) { for_const (auto &button, b) {
switch (button.type()) { switch (button.type()) {
@ -476,7 +504,9 @@ void HistoryMessageReplyMarkup::createFromButtonRows(const QVector<MTPKeyboardBu
} }
} }
} }
if (!buttonRow.isEmpty()) rows.push_back(buttonRow); if (!buttonRow.empty()) {
rows.push_back(std::move(buttonRow));
}
} }
} break; } break;
} }
@ -515,18 +545,21 @@ void HistoryMessageReplyMarkup::create(const MTPReplyMarkup &markup) {
} }
} }
void HistoryMessageReplyMarkup::create(const HistoryMessageReplyMarkup &markup) { void HistoryMessageReplyMarkup::create(
const HistoryMessageReplyMarkup &markup) {
flags = markup.flags; flags = markup.flags;
inlineKeyboard = nullptr; inlineKeyboard = nullptr;
rows.clear(); rows.clear();
for_const (auto &row, markup.rows) { for (const auto &row : markup.rows) {
ButtonRow buttonRow; auto buttonRow = std::vector<Button>();
buttonRow.reserve(row.size()); buttonRow.reserve(row.size());
for_const (auto &button, row) { for (const auto &button : row) {
buttonRow.push_back({ button.type, button.text, button.data, 0 }); buttonRow.push_back({ button.type, button.text, button.data, 0 });
} }
if (!buttonRow.isEmpty()) rows.push_back(buttonRow); if (!buttonRow.empty()) {
rows.push_back(std::move(buttonRow));
}
} }
} }

View File

@ -253,10 +253,8 @@ struct HistoryMessageReplyMarkup : public RuntimeComponent<HistoryMessageReplyMa
QByteArray data; QByteArray data;
mutable mtpRequestId requestId; mutable mtpRequestId requestId;
}; };
using ButtonRow = QVector<Button>;
using ButtonRows = QVector<ButtonRow>;
ButtonRows rows; std::vector<std::vector<Button>> rows;
MTPDreplyKeyboardMarkup::Flags flags = 0; MTPDreplyKeyboardMarkup::Flags flags = 0;
std::unique_ptr<ReplyKeyboard> inlineKeyboard; std::unique_ptr<ReplyKeyboard> inlineKeyboard;
@ -345,14 +343,15 @@ public:
friend class ReplyKeyboard; friend class ReplyKeyboard;
}; };
typedef std::unique_ptr<Style> StylePtr;
ReplyKeyboard(const HistoryItem *item, StylePtr &&s); ReplyKeyboard(
not_null<const HistoryItem*> item,
std::unique_ptr<Style> &&s);
ReplyKeyboard(const ReplyKeyboard &other) = delete; ReplyKeyboard(const ReplyKeyboard &other) = delete;
ReplyKeyboard &operator=(const ReplyKeyboard &other) = delete; ReplyKeyboard &operator=(const ReplyKeyboard &other) = delete;
bool isEnoughSpace(int width, const style::BotKeyboardButton &st) const; bool isEnoughSpace(int width, const style::BotKeyboardButton &st) const;
void setStyle(StylePtr &&s); void setStyle(std::unique_ptr<Style> &&s);
void resize(int width, int height); void resize(int width, int height);
// what width and height will best fit this keyboard // what width and height will best fit this keyboard
@ -369,39 +368,39 @@ public:
void updateMessageId(); void updateMessageId();
private: private:
void startAnimation(int i, int j, int direction);
friend class Style; friend class Style;
using ReplyMarkupClickHandlerPtr = std::shared_ptr<ReplyMarkupClickHandler>;
struct Button { struct Button {
Button();
Button(Button &&other);
Button &operator=(Button &&other);
~Button();
Text text = { 1 }; Text text = { 1 };
QRect rect; QRect rect;
int characters = 0; int characters = 0;
float64 howMuchOver = 0.; float64 howMuchOver = 0.;
HistoryMessageReplyMarkup::Button::Type type; HistoryMessageReplyMarkup::Button::Type type;
ReplyMarkupClickHandlerPtr link; std::shared_ptr<ReplyMarkupClickHandler> link;
mutable std::shared_ptr<Ui::RippleAnimation> ripple; mutable std::unique_ptr<Ui::RippleAnimation> ripple;
}; };
using ButtonRow = QVector<Button>;
using ButtonRows = QVector<ButtonRow>;
struct ButtonCoords { struct ButtonCoords {
int i, j; int i, j;
}; };
void startAnimation(int i, int j, int direction);
ButtonCoords findButtonCoordsByClickHandler(const ClickHandlerPtr &p); ButtonCoords findButtonCoordsByClickHandler(const ClickHandlerPtr &p);
using Animations = QMap<int, TimeMs>;
void step_selected(TimeMs ms, bool timer); void step_selected(TimeMs ms, bool timer);
const HistoryItem *_item; const not_null<const HistoryItem*> _item;
int _width = 0; int _width = 0;
ButtonRows _rows; std::vector<std::vector<Button>> _rows;
Animations _animations; base::flat_map<int, TimeMs> _animations;
BasicAnimation _a_selected; BasicAnimation _a_selected;
std::unique_ptr<Style> _st;
StylePtr _st;
ClickHandlerPtr _savedPressed; ClickHandlerPtr _savedPressed;
ClickHandlerPtr _savedActive; ClickHandlerPtr _savedActive;

View File

@ -1294,7 +1294,7 @@ void HistoryWidget::onRecordDone(QByteArray result, VoiceWaveform waveform, qint
auto duration = samples / Media::Player::kDefaultFrequency; auto duration = samples / Media::Player::kDefaultFrequency;
auto to = FileLoadTo(_peer->id, _peer->notifySilentPosts(), replyToId()); auto to = FileLoadTo(_peer->id, _peer->notifySilentPosts(), replyToId());
auto caption = QString(); auto caption = QString();
_fileLoader.addTask(std::make_shared<FileLoadTask>(result, duration, waveform, to, caption)); _fileLoader.addTask(std::make_unique<FileLoadTask>(result, duration, waveform, to, caption));
} }
void HistoryWidget::onRecordUpdate(quint16 level, qint32 samples) { void HistoryWidget::onRecordUpdate(quint16 level, qint32 samples) {
@ -4211,16 +4211,16 @@ void HistoryWidget::uploadFilesAfterConfirmation(
App::main()->sendMessage(message); App::main()->sendMessage(message);
caption = QString(); caption = QString();
} }
auto tasks = TasksList(); auto tasks = std::vector<std::unique_ptr<Task>>();
tasks.reserve(files.size()); tasks.reserve(files.size());
for_const (auto &filepath, files) { for_const (auto &filepath, files) {
if (filepath.isEmpty() && (!image.isNull() || !content.isNull())) { if (filepath.isEmpty() && (!image.isNull() || !content.isNull())) {
tasks.push_back(std::make_shared<FileLoadTask>(content, image, type, to, caption)); tasks.push_back(std::make_unique<FileLoadTask>(content, image, type, to, caption));
} else { } else {
tasks.push_back(std::make_shared<FileLoadTask>(filepath, std::move(information), type, to, caption)); tasks.push_back(std::make_unique<FileLoadTask>(filepath, std::move(information), type, to, caption));
} }
} }
_fileLoader.addTasks(tasks); _fileLoader.addTasks(std::move(tasks));
} }
void HistoryWidget::uploadFile(const QByteArray &fileContent, SendMediaType type) { void HistoryWidget::uploadFile(const QByteArray &fileContent, SendMediaType type) {
@ -4228,7 +4228,7 @@ void HistoryWidget::uploadFile(const QByteArray &fileContent, SendMediaType type
auto to = FileLoadTo(_peer->id, _peer->notifySilentPosts(), replyToId()); auto to = FileLoadTo(_peer->id, _peer->notifySilentPosts(), replyToId());
auto caption = QString(); auto caption = QString();
_fileLoader.addTask(std::make_shared<FileLoadTask>(fileContent, QImage(), type, to, caption)); _fileLoader.addTask(std::make_unique<FileLoadTask>(fileContent, QImage(), type, to, caption));
} }
void HistoryWidget::sendFileConfirmed(const FileLoadResultPtr &file) { void HistoryWidget::sendFileConfirmed(const FileLoadResultPtr &file) {

View File

@ -114,7 +114,7 @@ public:
} }
private: private:
std::shared_ptr<QFile> files[LogDataCount]; std::unique_ptr<QFile> files[LogDataCount];
QTextStream streams[LogDataCount]; QTextStream streams[LogDataCount];
int32 part = -1; int32 part = -1;
@ -136,7 +136,7 @@ private:
if (postfix.isEmpty()) { // instance checked, need to move to log.txt if (postfix.isEmpty()) { // instance checked, need to move to log.txt
Assert(!files[type]->fileName().isEmpty()); // one of log_startXX.txt should've been opened already Assert(!files[type]->fileName().isEmpty()); // one of log_startXX.txt should've been opened already
std::shared_ptr<QFile> to = std::make_shared<QFile>(_logsFilePath(type, postfix)); auto to = std::make_unique<QFile>(_logsFilePath(type, postfix));
if (to->exists() && !to->remove()) { if (to->exists() && !to->remove()) {
LOG(("Could not delete '%1' file to start new logging!").arg(to->fileName())); LOG(("Could not delete '%1' file to start new logging!").arg(to->fileName()));
return false; return false;

View File

@ -365,7 +365,7 @@ private:
LinkEntry(const QString &url, const QString &text); LinkEntry(const QString &url, const QString &text);
QString text; QString text;
int32 width; int32 width;
TextClickHandlerPtr lnk; std::shared_ptr<TextClickHandler> lnk;
}; };
QVector<LinkEntry> _links; QVector<LinkEntry> _links;

View File

@ -55,7 +55,7 @@ void Uploader::uploadMedia(const FullMsgId &msgId, const SendMediaReady &media)
document->setLocation(FileLocation(media.file)); document->setLocation(FileLocation(media.file));
} }
} }
queue.insert(msgId, File(media)); queue.emplace(msgId, File(media));
sendNext(); sendNext();
} }
@ -73,21 +73,21 @@ void Uploader::upload(const FullMsgId &msgId, const FileLoadResultPtr &file) {
document->setLocation(FileLocation(file->filepath)); document->setLocation(FileLocation(file->filepath));
} }
} }
queue.insert(msgId, File(file)); queue.emplace(msgId, File(file));
sendNext(); sendNext();
} }
void Uploader::currentFailed() { void Uploader::currentFailed() {
Queue::iterator j = queue.find(uploading); auto j = queue.find(uploadingId);
if (j != queue.end()) { if (j != queue.end()) {
if (j->type() == SendMediaType::Photo) { if (j->second.type() == SendMediaType::Photo) {
emit photoFailed(j.key()); emit photoFailed(j->first);
} else if (j->type() == SendMediaType::File) { } else if (j->second.type() == SendMediaType::File) {
DocumentData *doc = App::document(j->id()); const auto document = App::document(j->second.id());
if (doc->status == FileUploading) { if (document->status == FileUploading) {
doc->status = FileUploadFailed; document->status = FileUploadFailed;
} }
emit documentFailed(j.key()); emit documentFailed(j->first);
} }
queue.erase(j); queue.erase(j);
} }
@ -95,7 +95,7 @@ void Uploader::currentFailed() {
requestsSent.clear(); requestsSent.clear();
docRequestsSent.clear(); docRequestsSent.clear();
dcMap.clear(); dcMap.clear();
uploading = FullMsgId(); uploadingId = FullMsgId();
sentSize = 0; sentSize = 0;
for (int i = 0; i < MTP::kUploadSessionsCount; ++i) { for (int i = 0; i < MTP::kUploadSessionsCount; ++i) {
sentSizes[i] = 0; sentSizes[i] = 0;
@ -111,10 +111,10 @@ void Uploader::killSessions() {
} }
void Uploader::sendNext() { void Uploader::sendNext() {
if (sentSize >= kMaxUploadFileParallelSize || _paused.msg) return; if (sentSize >= kMaxUploadFileParallelSize || _pausedId.msg) return;
bool killing = killSessionsTimer.isActive(); bool killing = killSessionsTimer.isActive();
if (queue.isEmpty()) { if (queue.empty()) {
if (!killing) { if (!killing) {
killSessionsTimer.start(MTPAckSendWaiting + MTPKillFileSessionTimeout); killSessionsTimer.start(MTPAckSendWaiting + MTPKillFileSessionTimeout);
} }
@ -124,95 +124,172 @@ void Uploader::sendNext() {
if (killing) { if (killing) {
killSessionsTimer.stop(); killSessionsTimer.stop();
} }
Queue::iterator i = uploading.msg ? queue.find(uploading) : queue.begin(); auto i = uploadingId.msg ? queue.find(uploadingId) : queue.begin();
if (!uploading.msg) { if (!uploadingId.msg) {
uploading = i.key(); uploadingId = i->first;
} else if (i == queue.end()) { } else if (i == queue.end()) {
i = queue.begin(); i = queue.begin();
uploading = i.key(); uploadingId = i->first;
} }
int todc = 0; auto &uploadingData = i->second;
for (int dc = 1; dc < MTP::kUploadSessionsCount; ++dc) {
auto todc = 0;
for (auto dc = 1; dc != MTP::kUploadSessionsCount; ++dc) {
if (sentSizes[dc] < sentSizes[todc]) { if (sentSizes[dc] < sentSizes[todc]) {
todc = dc; todc = dc;
} }
} }
UploadFileParts &parts(i->file ? (i->type() == SendMediaType::Photo ? i->file->fileparts : i->file->thumbparts) : i->media.parts); auto &parts = uploadingData.file
uint64 partsOfId(i->file ? (i->type() == SendMediaType::Photo ? i->file->id : i->file->thumbId) : i->media.thumbId); ? (uploadingData.type() == SendMediaType::Photo
? uploadingData.file->fileparts
: uploadingData.file->thumbparts)
: uploadingData.media.parts;
const auto partsOfId = uploadingData.file
? (uploadingData.type() == SendMediaType::Photo
? uploadingData.file->id
: uploadingData.file->thumbId)
: uploadingData.media.thumbId;
if (parts.isEmpty()) { if (parts.isEmpty()) {
if (i->docSentParts >= i->docPartsCount) { if (uploadingData.docSentParts >= uploadingData.docPartsCount) {
if (requestsSent.isEmpty() && docRequestsSent.isEmpty()) { if (requestsSent.empty() && docRequestsSent.empty()) {
bool silent = i->file && i->file->to.silent; const auto silent = uploadingData.file
if (i->type() == SendMediaType::Photo) { && uploadingData.file->to.silent;
auto photoFilename = i->filename(); if (uploadingData.type() == SendMediaType::Photo) {
auto photoFilename = uploadingData.filename();
if (!photoFilename.endsWith(qstr(".jpg"), Qt::CaseInsensitive)) { if (!photoFilename.endsWith(qstr(".jpg"), Qt::CaseInsensitive)) {
// Server has some extensions checking for inputMediaUploadedPhoto, // Server has some extensions checking for inputMediaUploadedPhoto,
// so force the extension to be .jpg anyway. It doesn't matter, // so force the extension to be .jpg anyway. It doesn't matter,
// because the filename from inputFile is not used anywhere. // because the filename from inputFile is not used anywhere.
photoFilename += qstr(".jpg"); photoFilename += qstr(".jpg");
} }
emit photoReady(uploading, silent, MTP_inputFile(MTP_long(i->id()), MTP_int(i->partsCount), MTP_string(photoFilename), MTP_bytes(i->file ? i->file->filemd5 : i->media.jpeg_md5))); const auto md5 = uploadingData.file
} else if (i->type() == SendMediaType::File || i->type() == SendMediaType::Audio) { ? uploadingData.file->filemd5
: uploadingData.media.jpeg_md5;
const auto file = MTP_inputFile(
MTP_long(uploadingData.id()),
MTP_int(uploadingData.partsCount),
MTP_string(photoFilename),
MTP_bytes(md5));
emit photoReady(uploadingId, silent, file);
} else if (uploadingData.type() == SendMediaType::File
|| uploadingData.type() == SendMediaType::Audio) {
QByteArray docMd5(32, Qt::Uninitialized); QByteArray docMd5(32, Qt::Uninitialized);
hashMd5Hex(i->md5Hash.result(), docMd5.data()); hashMd5Hex(uploadingData.md5Hash.result(), docMd5.data());
MTPInputFile doc = (i->docSize > UseBigFilesFrom) ? MTP_inputFileBig(MTP_long(i->id()), MTP_int(i->docPartsCount), MTP_string(i->filename())) : MTP_inputFile(MTP_long(i->id()), MTP_int(i->docPartsCount), MTP_string(i->filename()), MTP_bytes(docMd5)); const auto file = (uploadingData.docSize > UseBigFilesFrom)
if (i->partsCount) { ? MTP_inputFileBig(
emit thumbDocumentReady(uploading, silent, doc, MTP_inputFile(MTP_long(i->thumbId()), MTP_int(i->partsCount), MTP_string(i->file ? i->file->thumbname : (qsl("thumb.") + i->media.thumbExt)), MTP_bytes(i->file ? i->file->thumbmd5 : i->media.jpeg_md5))); MTP_long(uploadingData.id()),
MTP_int(uploadingData.docPartsCount),
MTP_string(uploadingData.filename()))
: MTP_inputFile(
MTP_long(uploadingData.id()),
MTP_int(uploadingData.docPartsCount),
MTP_string(uploadingData.filename()),
MTP_bytes(docMd5));
if (uploadingData.partsCount) {
const auto thumbFilename = uploadingData.file
? uploadingData.file->thumbname
: (qsl("thumb.") + uploadingData.media.thumbExt);
const auto thumbMd5 = uploadingData.file
? uploadingData.file->thumbmd5
: uploadingData.media.jpeg_md5;
const auto thumb = MTP_inputFile(
MTP_long(uploadingData.thumbId()),
MTP_int(uploadingData.partsCount),
MTP_string(thumbFilename),
MTP_bytes(thumbMd5));
emit thumbDocumentReady(
uploadingId,
silent,
file,
thumb);
} else { } else {
emit documentReady(uploading, silent, doc); emit documentReady(uploadingId, silent, file);
} }
} }
queue.remove(uploading); queue.erase(uploadingId);
uploading = FullMsgId(); uploadingId = FullMsgId();
sendNext(); sendNext();
} }
return; return;
} }
QByteArray &content(i->file ? i->file->content : i->media.data); auto &content = uploadingData.file
? uploadingData.file->content
: uploadingData.media.data;
QByteArray toSend; QByteArray toSend;
if (content.isEmpty()) { if (content.isEmpty()) {
if (!i->docFile) { if (!uploadingData.docFile) {
i->docFile.reset(new QFile(i->file ? i->file->filepath : i->media.file)); const auto filepath = uploadingData.file
if (!i->docFile->open(QIODevice::ReadOnly)) { ? uploadingData.file->filepath
: uploadingData.media.file;
uploadingData.docFile = std::make_unique<QFile>(filepath);
if (!uploadingData.docFile->open(QIODevice::ReadOnly)) {
currentFailed(); currentFailed();
return; return;
} }
} }
toSend = i->docFile->read(i->docPartSize); toSend = uploadingData.docFile->read(uploadingData.docPartSize);
if (i->docSize <= UseBigFilesFrom) { if (uploadingData.docSize <= UseBigFilesFrom) {
i->md5Hash.feed(toSend.constData(), toSend.size()); uploadingData.md5Hash.feed(toSend.constData(), toSend.size());
} }
} else { } else {
toSend = content.mid(i->docSentParts * i->docPartSize, i->docPartSize); const auto offset = uploadingData.docSentParts
if ((i->type() == SendMediaType::File || i->type() == SendMediaType::Audio) && i->docSentParts <= UseBigFilesFrom) { * uploadingData.docPartSize;
i->md5Hash.feed(toSend.constData(), toSend.size()); toSend = content.mid(offset, uploadingData.docPartSize);
if ((uploadingData.type() == SendMediaType::File
|| uploadingData.type() == SendMediaType::Audio)
&& uploadingData.docSentParts <= UseBigFilesFrom) {
uploadingData.md5Hash.feed(toSend.constData(), toSend.size());
} }
} }
if (toSend.size() > i->docPartSize || (toSend.size() < i->docPartSize && i->docSentParts + 1 != i->docPartsCount)) { if ((toSend.size() > uploadingData.docPartSize)
|| ((toSend.size() < uploadingData.docPartSize
&& uploadingData.docSentParts + 1 != uploadingData.docPartsCount))) {
currentFailed(); currentFailed();
return; return;
} }
mtpRequestId requestId; mtpRequestId requestId;
if (i->docSize > UseBigFilesFrom) { if (uploadingData.docSize > UseBigFilesFrom) {
requestId = MTP::send(MTPupload_SaveBigFilePart(MTP_long(i->id()), MTP_int(i->docSentParts), MTP_int(i->docPartsCount), MTP_bytes(toSend)), rpcDone(&Uploader::partLoaded), rpcFail(&Uploader::partFailed), MTP::uploadDcId(todc)); requestId = MTP::send(
MTPupload_SaveBigFilePart(
MTP_long(uploadingData.id()),
MTP_int(uploadingData.docSentParts),
MTP_int(uploadingData.docPartsCount),
MTP_bytes(toSend)),
rpcDone(&Uploader::partLoaded),
rpcFail(&Uploader::partFailed),
MTP::uploadDcId(todc));
} else { } else {
requestId = MTP::send(MTPupload_SaveFilePart(MTP_long(i->id()), MTP_int(i->docSentParts), MTP_bytes(toSend)), rpcDone(&Uploader::partLoaded), rpcFail(&Uploader::partFailed), MTP::uploadDcId(todc)); requestId = MTP::send(
MTPupload_SaveFilePart(
MTP_long(uploadingData.id()),
MTP_int(uploadingData.docSentParts),
MTP_bytes(toSend)),
rpcDone(&Uploader::partLoaded),
rpcFail(&Uploader::partFailed),
MTP::uploadDcId(todc));
} }
docRequestsSent.insert(requestId, i->docSentParts); docRequestsSent.emplace(requestId, uploadingData.docSentParts);
dcMap.insert(requestId, todc); dcMap.emplace(requestId, todc);
sentSize += i->docPartSize; sentSize += uploadingData.docPartSize;
sentSizes[todc] += i->docPartSize; sentSizes[todc] += uploadingData.docPartSize;
i->docSentParts++; uploadingData.docSentParts++;
} else { } else {
UploadFileParts::iterator part = parts.begin(); auto part = parts.begin();
mtpRequestId requestId = MTP::send(MTPupload_SaveFilePart(MTP_long(partsOfId), MTP_int(part.key()), MTP_bytes(part.value())), rpcDone(&Uploader::partLoaded), rpcFail(&Uploader::partFailed), MTP::uploadDcId(todc)); const auto requestId = MTP::send(
requestsSent.insert(requestId, part.value()); MTPupload_SaveFilePart(
dcMap.insert(requestId, todc); MTP_long(partsOfId),
MTP_int(part.key()),
MTP_bytes(part.value())),
rpcDone(&Uploader::partLoaded),
rpcFail(&Uploader::partFailed),
MTP::uploadDcId(todc));
requestsSent.emplace(requestId, part.value());
dcMap.emplace(requestId, todc);
sentSize += part.value().size(); sentSize += part.value().size();
sentSizes[todc] += part.value().size(); sentSizes[todc] += part.value().size();
@ -222,20 +299,20 @@ void Uploader::sendNext() {
} }
void Uploader::cancel(const FullMsgId &msgId) { void Uploader::cancel(const FullMsgId &msgId) {
uploaded.remove(msgId); uploaded.erase(msgId);
if (uploading == msgId) { if (uploadingId == msgId) {
currentFailed(); currentFailed();
} else { } else {
queue.remove(msgId); queue.erase(msgId);
} }
} }
void Uploader::pause(const FullMsgId &msgId) { void Uploader::pause(const FullMsgId &msgId) {
_paused = msgId; _pausedId = msgId;
} }
void Uploader::unpause() { void Uploader::unpause() {
_paused = FullMsgId(); _pausedId = FullMsgId();
sendNext(); sendNext();
} }
@ -245,12 +322,12 @@ void Uploader::confirm(const FullMsgId &msgId) {
void Uploader::clear() { void Uploader::clear() {
uploaded.clear(); uploaded.clear();
queue.clear(); queue.clear();
for (QMap<mtpRequestId, QByteArray>::const_iterator i = requestsSent.cbegin(), e = requestsSent.cend(); i != e; ++i) { for (const auto &[requestId, requestData] : requestsSent) {
MTP::cancel(i.key()); MTP::cancel(requestId);
} }
requestsSent.clear(); requestsSent.clear();
for (QMap<mtpRequestId, int32>::const_iterator i = docRequestsSent.cbegin(), e = docRequestsSent.cend(); i != e; ++i) { for (const auto &[requestId, requestIndex] : docRequestsSent) {
MTP::cancel(i.key()); MTP::cancel(requestId);
} }
docRequestsSent.clear(); docRequestsSent.clear();
dcMap.clear(); dcMap.clear();
@ -263,8 +340,8 @@ void Uploader::clear() {
} }
void Uploader::partLoaded(const MTPBool &result, mtpRequestId requestId) { void Uploader::partLoaded(const MTPBool &result, mtpRequestId requestId) {
QMap<mtpRequestId, int32>::iterator j = docRequestsSent.end(); auto j = docRequestsSent.end();
QMap<mtpRequestId, QByteArray>::iterator i = requestsSent.find(requestId); auto i = requestsSent.find(requestId);
if (i == requestsSent.cend()) { if (i == requestsSent.cend()) {
j = docRequestsSent.find(requestId); j = docRequestsSent.find(requestId);
} }
@ -273,42 +350,47 @@ void Uploader::partLoaded(const MTPBool &result, mtpRequestId requestId) {
currentFailed(); currentFailed();
return; return;
} else { } else {
QMap<mtpRequestId, int32>::iterator dcIt = dcMap.find(requestId); auto dcIt = dcMap.find(requestId);
if (dcIt == dcMap.cend()) { // must not happen if (dcIt == dcMap.cend()) { // must not happen
currentFailed(); currentFailed();
return; return;
} }
int32 dc = dcIt.value(); auto dc = dcIt->second;
dcMap.erase(dcIt); dcMap.erase(dcIt);
int32 sentPartSize = 0; int32 sentPartSize = 0;
Queue::const_iterator k = queue.constFind(uploading); auto k = queue.find(uploadingId);
Assert(k != queue.cend());
auto &[fullId, file] = *k;
if (i != requestsSent.cend()) { if (i != requestsSent.cend()) {
sentPartSize = i.value().size(); sentPartSize = i->second.size();
requestsSent.erase(i); requestsSent.erase(i);
} else { } else {
sentPartSize = k->docPartSize; sentPartSize = file.docPartSize;
docRequestsSent.erase(j); docRequestsSent.erase(j);
} }
sentSize -= sentPartSize; sentSize -= sentPartSize;
sentSizes[dc] -= sentPartSize; sentSizes[dc] -= sentPartSize;
if (k->type() == SendMediaType::Photo) { if (file.type() == SendMediaType::Photo) {
k->fileSentSize += sentPartSize; file.fileSentSize += sentPartSize;
PhotoData *photo = App::photo(k->id()); const auto photo = App::photo(file.id());
if (photo->uploading() && k->file) { if (photo->uploading() && file.file) {
photo->uploadingData->size = k->file->partssize; photo->uploadingData->size = file.file->partssize;
photo->uploadingData->offset = k->fileSentSize; photo->uploadingData->offset = file.fileSentSize;
} }
emit photoProgress(k.key()); emit photoProgress(fullId);
} else if (k->type() == SendMediaType::File || k->type() == SendMediaType::Audio) { } else if (file.type() == SendMediaType::File
DocumentData *doc = App::document(k->id()); || file.type() == SendMediaType::Audio) {
if (doc->uploading()) { const auto document = App::document(file.id());
doc->uploadOffset = (k->docSentParts - docRequestsSent.size()) * k->docPartSize; if (document->uploading()) {
if (doc->uploadOffset > doc->size) { const auto doneParts = file.docSentParts
doc->uploadOffset = doc->size; - int(docRequestsSent.size());
document->uploadOffset = doneParts * file.docPartSize;
if (document->uploadOffset > document->size) {
document->uploadOffset = document->size;
} }
} }
emit documentProgress(k.key()); emit documentProgress(fullId);
} }
} }
} }
@ -319,7 +401,9 @@ void Uploader::partLoaded(const MTPBool &result, mtpRequestId requestId) {
bool Uploader::partFailed(const RPCError &error, mtpRequestId requestId) { bool Uploader::partFailed(const RPCError &error, mtpRequestId requestId) {
if (MTP::isDefaultHandledError(error)) return false; if (MTP::isDefaultHandledError(error)) return false;
if (requestsSent.constFind(requestId) != requestsSent.cend() || docRequestsSent.constFind(requestId) != docRequestsSent.cend()) { // failed to upload current file // failed to upload current file
if ((requestsSent.find(requestId) != requestsSent.cend())
|| (docRequestsSent.find(requestId) != docRequestsSent.cend())) {
currentFailed(); currentFailed();
} }
sendNext(); sendNext();

View File

@ -117,28 +117,28 @@ private:
HashMd5 md5Hash; HashMd5 md5Hash;
std::shared_ptr<QFile> docFile; std::unique_ptr<QFile> docFile;
int32 docSentParts; int32 docSentParts;
int32 docSize; int32 docSize;
int32 docPartSize; int32 docPartSize;
int32 docPartsCount; int32 docPartsCount;
}; };
typedef QMap<FullMsgId, File> Queue;
void partLoaded(const MTPBool &result, mtpRequestId requestId); void partLoaded(const MTPBool &result, mtpRequestId requestId);
bool partFailed(const RPCError &err, mtpRequestId requestId); bool partFailed(const RPCError &err, mtpRequestId requestId);
void currentFailed(); void currentFailed();
QMap<mtpRequestId, QByteArray> requestsSent; base::flat_map<mtpRequestId, QByteArray> requestsSent;
QMap<mtpRequestId, int32> docRequestsSent; base::flat_map<mtpRequestId, int32> docRequestsSent;
QMap<mtpRequestId, int32> dcMap; base::flat_map<mtpRequestId, int32> dcMap;
uint32 sentSize = 0; uint32 sentSize = 0;
uint32 sentSizes[MTP::kUploadSessionsCount] = { 0 }; uint32 sentSizes[MTP::kUploadSessionsCount] = { 0 };
FullMsgId uploading, _paused; FullMsgId uploadingId;
Queue queue; FullMsgId _pausedId;
Queue uploaded; std::map<FullMsgId, File> queue;
std::map<FullMsgId, File> uploaded;
QTimer nextTimer, killSessionsTimer; QTimer nextTimer, killSessionsTimer;
}; };

View File

@ -48,21 +48,24 @@ TaskQueue::TaskQueue(QObject *parent, int32 stopTimeoutMs) : QObject(parent), _t
} }
} }
TaskId TaskQueue::addTask(TaskPtr task) { TaskId TaskQueue::addTask(std::unique_ptr<Task> &&task) {
const auto result = task->id();
{ {
QMutexLocker lock(&_tasksToProcessMutex); QMutexLocker lock(&_tasksToProcessMutex);
_tasksToProcess.push_back(task); _tasksToProcess.push_back(std::move(task));
} }
wakeThread(); wakeThread();
return task->id(); return result;
} }
void TaskQueue::addTasks(const TasksList &tasks) { void TaskQueue::addTasks(std::vector<std::unique_ptr<Task>> &&tasks) {
{ {
QMutexLocker lock(&_tasksToProcessMutex); QMutexLocker lock(&_tasksToProcessMutex);
_tasksToProcess.append(tasks); for (auto &task : tasks) {
_tasksToProcess.push_back(std::move(task));
}
} }
wakeThread(); wakeThread();
@ -85,31 +88,33 @@ void TaskQueue::wakeThread() {
} }
void TaskQueue::cancelTask(TaskId id) { void TaskQueue::cancelTask(TaskId id) {
const auto removeFrom = [&](std::deque<std::unique_ptr<Task>> &queue) {
const auto proj = [](const std::unique_ptr<Task> &task) {
return task->id();
};
auto i = ranges::find(queue, id, proj);
if (i != queue.end()) {
queue.erase(i);
}
};
{ {
QMutexLocker lock(&_tasksToProcessMutex); QMutexLocker lock(&_tasksToProcessMutex);
for (int32 i = 0, l = _tasksToProcess.size(); i != l; ++i) { removeFrom(_tasksToProcess);
if (_tasksToProcess.at(i)->id() == id) { if (_taskInProcessId == id) {
_tasksToProcess.removeAt(i); _taskInProcessId = TaskId();
return;
}
} }
} }
QMutexLocker lock(&_tasksToFinishMutex); QMutexLocker lock(&_tasksToFinishMutex);
for (int32 i = 0, l = _tasksToFinish.size(); i != l; ++i) { removeFrom(_tasksToFinish);
if (_tasksToFinish.at(i)->id() == id) {
_tasksToFinish.removeAt(i);
return;
}
}
} }
void TaskQueue::onTaskProcessed() { void TaskQueue::onTaskProcessed() {
do { do {
TaskPtr task; auto task = std::unique_ptr<Task>();
{ {
QMutexLocker lock(&_tasksToFinishMutex); QMutexLocker lock(&_tasksToFinishMutex);
if (_tasksToFinish.isEmpty()) break; if (_tasksToFinish.empty()) break;
task = _tasksToFinish.front(); task = std::move(_tasksToFinish.front());
_tasksToFinish.pop_front(); _tasksToFinish.pop_front();
} }
task->finish(); task->finish();
@ -117,7 +122,7 @@ void TaskQueue::onTaskProcessed() {
if (_stopTimer) { if (_stopTimer) {
QMutexLocker lock(&_tasksToProcessMutex); QMutexLocker lock(&_tasksToProcessMutex);
if (_tasksToProcess.isEmpty()) { if (_tasksToProcess.empty() && !_taskInProcessId) {
_stopTimer->start(); _stopTimer->start();
} }
} }
@ -136,6 +141,7 @@ void TaskQueue::stop() {
} }
_tasksToProcess.clear(); _tasksToProcess.clear();
_tasksToFinish.clear(); _tasksToFinish.clear();
_taskInProcessId = TaskId();
} }
TaskQueue::~TaskQueue() { TaskQueue::~TaskQueue() {
@ -149,11 +155,13 @@ void TaskQueueWorker::onTaskAdded() {
bool someTasksLeft = false; bool someTasksLeft = false;
do { do {
TaskPtr task; auto task = std::unique_ptr<Task>();
{ {
QMutexLocker lock(&_queue->_tasksToProcessMutex); QMutexLocker lock(&_queue->_tasksToProcessMutex);
if (!_queue->_tasksToProcess.isEmpty()) { if (!_queue->_tasksToProcess.empty()) {
task = _queue->_tasksToProcess.front(); task = std::move(_queue->_tasksToProcess.front());
_queue->_tasksToProcess.pop_front();
_queue->_taskInProcessId = task->id();
} }
} }
@ -162,13 +170,13 @@ void TaskQueueWorker::onTaskAdded() {
bool emitTaskProcessed = false; bool emitTaskProcessed = false;
{ {
QMutexLocker lockToProcess(&_queue->_tasksToProcessMutex); QMutexLocker lockToProcess(&_queue->_tasksToProcessMutex);
if (!_queue->_tasksToProcess.isEmpty() && _queue->_tasksToProcess.front() == task) { if (_queue->_taskInProcessId == task->id()) {
_queue->_tasksToProcess.pop_front(); _queue->_taskInProcessId = TaskId();
someTasksLeft = !_queue->_tasksToProcess.isEmpty(); someTasksLeft = !_queue->_tasksToProcess.empty();
QMutexLocker lockToFinish(&_queue->_tasksToFinishMutex); QMutexLocker lockToFinish(&_queue->_tasksToFinishMutex);
emitTaskProcessed = _queue->_tasksToFinish.isEmpty(); emitTaskProcessed = _queue->_tasksToFinish.empty();
_queue->_tasksToFinish.push_back(task); _queue->_tasksToFinish.push_back(std::move(task));
} }
} }
if (emitTaskProcessed) { if (emitTaskProcessed) {

View File

@ -114,8 +114,6 @@ public:
} }
}; };
using TaskPtr = std::shared_ptr<Task>;
using TasksList = QList<TaskPtr>;
class TaskQueueWorker; class TaskQueueWorker;
class TaskQueue : public QObject { class TaskQueue : public QObject {
@ -124,8 +122,8 @@ class TaskQueue : public QObject {
public: public:
TaskQueue(QObject *parent, int32 stopTimeoutMs = 0); // <= 0 - never stop worker TaskQueue(QObject *parent, int32 stopTimeoutMs = 0); // <= 0 - never stop worker
TaskId addTask(TaskPtr task); TaskId addTask(std::unique_ptr<Task> &&task);
void addTasks(const TasksList &tasks); void addTasks(std::vector<std::unique_ptr<Task>> &&tasks);
void cancelTask(TaskId id); // this task finish() won't be called void cancelTask(TaskId id); // this task finish() won't be called
~TaskQueue(); ~TaskQueue();
@ -142,7 +140,9 @@ private:
void wakeThread(); void wakeThread();
TasksList _tasksToProcess, _tasksToFinish; std::deque<std::unique_ptr<Task>> _tasksToProcess;
std::deque<std::unique_ptr<Task>> _tasksToFinish;
TaskId _taskInProcessId = TaskId();
QMutex _tasksToProcessMutex, _tasksToFinishMutex; QMutex _tasksToProcessMutex, _tasksToFinishMutex;
QThread *_thread; QThread *_thread;
TaskQueueWorker *_worker; TaskQueueWorker *_worker;

View File

@ -165,9 +165,7 @@ void createLocalKey(const QByteArray &pass, QByteArray *salt, MTP::AuthKeyPtr *r
} }
struct FileReadDescriptor { struct FileReadDescriptor {
FileReadDescriptor() : version(0) { int32 version = 0;
}
int32 version;
QByteArray data; QByteArray data;
QBuffer buffer; QBuffer buffer;
QDataStream stream; QDataStream stream;
@ -2854,7 +2852,8 @@ TaskId startImageLoad(const StorageKey &location, mtpFileLoader *loader) {
if (j == _imagesMap.cend() || !_localLoader) { if (j == _imagesMap.cend() || !_localLoader) {
return 0; return 0;
} }
return _localLoader->addTask(std::make_shared<ImageLoadTask>(j->first, location, loader)); return _localLoader->addTask(
std::make_unique<ImageLoadTask>(j->first, location, loader));
} }
int32 hasImages() { int32 hasImages() {
@ -2912,7 +2911,8 @@ TaskId startStickerImageLoad(const StorageKey &location, mtpFileLoader *loader)
if (j == _stickerImagesMap.cend() || !_localLoader) { if (j == _stickerImagesMap.cend() || !_localLoader) {
return 0; return 0;
} }
return _localLoader->addTask(std::make_shared<StickerImageLoadTask>(j->first, location, loader)); return _localLoader->addTask(
std::make_unique<StickerImageLoadTask>(j->first, location, loader));
} }
bool willStickerImageLoad(const StorageKey &location) { bool willStickerImageLoad(const StorageKey &location) {
@ -2985,7 +2985,8 @@ TaskId startAudioLoad(const StorageKey &location, mtpFileLoader *loader) {
if (j == _audiosMap.cend() || !_localLoader) { if (j == _audiosMap.cend() || !_localLoader) {
return 0; return 0;
} }
return _localLoader->addTask(std::make_shared<AudioLoadTask>(j->first, location, loader)); return _localLoader->addTask(
std::make_unique<AudioLoadTask>(j->first, location, loader));
} }
bool copyAudio(const StorageKey &oldLocation, const StorageKey &newLocation) { bool copyAudio(const StorageKey &oldLocation, const StorageKey &newLocation) {
@ -3101,7 +3102,8 @@ TaskId startWebFileLoad(const QString &url, webFileLoader *loader) {
if (j == _webFilesMap.cend() || !_localLoader) { if (j == _webFilesMap.cend() || !_localLoader) {
return 0; return 0;
} }
return _localLoader->addTask(std::make_shared<WebFileLoadTask>(j->first, url, loader)); return _localLoader->addTask(
std::make_unique<WebFileLoadTask>(j->first, url, loader));
} }
int32 hasWebFiles() { int32 hasWebFiles() {
@ -3177,7 +3179,8 @@ void countVoiceWaveform(DocumentData *document) {
if (_localLoader) { if (_localLoader) {
voice->waveform.resize(1 + sizeof(TaskId)); voice->waveform.resize(1 + sizeof(TaskId));
voice->waveform[0] = -1; // counting voice->waveform[0] = -1; // counting
TaskId taskId = _localLoader->addTask(std::make_shared<CountWaveformTask>(document)); TaskId taskId = _localLoader->addTask(
std::make_unique<CountWaveformTask>(document));
memcpy(voice->waveform.data() + 1, &taskId, sizeof(taskId)); memcpy(voice->waveform.data() + 1, &taskId, sizeof(taskId));
} }
} }

View File

@ -91,7 +91,8 @@ void DiscreteSlider::setSections(const QStringList &labels) {
} }
int DiscreteSlider::getCurrentActiveLeft(TimeMs ms) { int DiscreteSlider::getCurrentActiveLeft(TimeMs ms) {
return _a_left.current(ms, _sections.isEmpty() ? 0 : _sections[_selected].left); const auto left = _sections.empty() ? 0 : _sections[_selected].left;
return _a_left.current(ms, left);
} }
template <typename Lambda> template <typename Lambda>
@ -253,9 +254,13 @@ void SettingsSlider::startRipple(int sectionIndex) {
if (index++ == sectionIndex) { if (index++ == sectionIndex) {
if (!section.ripple) { if (!section.ripple) {
auto mask = prepareRippleMask(sectionIndex, section); auto mask = prepareRippleMask(sectionIndex, section);
section.ripple = std::make_shared<RippleAnimation>(_st.ripple, std::move(mask), [this] { update(); }); section.ripple = std::make_unique<RippleAnimation>(
_st.ripple,
std::move(mask),
[this] { update(); });
} }
section.ripple->add(mapFromGlobal(QCursor::pos()) - QPoint(section.left, 0)); const auto point = mapFromGlobal(QCursor::pos());
section.ripple->add(point - QPoint(section.left, 0));
return false; return false;
} }
return true; return true;

View File

@ -59,7 +59,7 @@ protected:
int left, width; int left, width;
QString label; QString label;
int labelWidth; int labelWidth;
std::shared_ptr<RippleAnimation> ripple; std::unique_ptr<RippleAnimation> ripple;
}; };
int getCurrentActiveLeft(TimeMs ms); int getCurrentActiveLeft(TimeMs ms);
@ -91,7 +91,7 @@ private:
int getIndexFromPosition(QPoint pos); int getIndexFromPosition(QPoint pos);
void setSelectedSection(int index); void setSelectedSection(int index);
QList<Section> _sections; std::vector<Section> _sections;
int _activeIndex = 0; int _activeIndex = 0;
bool _selectOnPress = true; bool _selectOnPress = true;