diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 854033fda..f42208f72 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1098,10 +1098,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org "lng_send_images_selected#other" = "{count} images selected"; "lng_send_photos#one" = "Send {count} photo"; "lng_send_photos#other" = "Send {count} photos"; -"lng_send_photos_videos#one" = "Send {count} photo and video file"; -"lng_send_photos_videos#other" = "Send {count} photos and video files"; +"lng_send_photos_videos#one" = "Send {count} photo and video"; +"lng_send_photos_videos#other" = "Send {count} photos and videos"; "lng_send_separate_photos" = "Send separate photos"; -"lng_send_separate_photos_videos" = "Send separate photos and video files"; +"lng_send_separate_photos_videos" = "Send separate photos and videos"; "lng_send_files_selected#one" = "{count} file selected"; "lng_send_files_selected#other" = "{count} files selected"; "lng_send_files#one" = "Send {count} file"; diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 3fb18c170..eb71c2453 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -2743,6 +2743,9 @@ void ApiWrap::sendFiles( } const auto to = FileLoadTaskOptions(options); + if (album) { + album->silent = to.silent; + } auto tasks = std::vector>(); tasks.reserve(list.files.size()); for (auto &file : list.files) { @@ -2806,7 +2809,7 @@ void ApiWrap::sendUploadedPhoto( MTPVector(), MTP_int(0)); if (const auto groupId = item->groupId()) { - uploadAlbumMedia(item, groupId, media, silent); + uploadAlbumMedia(item, groupId, media); } else { sendMedia(item, media, silent); } @@ -2840,7 +2843,7 @@ void ApiWrap::sendUploadedDocument( MTPVector(), MTP_int(0)); if (groupId) { - uploadAlbumMedia(item, groupId, media, silent); + uploadAlbumMedia(item, groupId, media); } else { sendMedia(item, media, silent); } @@ -2848,11 +2851,18 @@ void ApiWrap::sendUploadedDocument( } } +void ApiWrap::cancelLocalItem(not_null item) { + Expects(!IsServerMsgId(item->id)); + + if (const auto groupId = item->groupId()) { + sendAlbumWithCancelled(item, groupId); + } +} + void ApiWrap::uploadAlbumMedia( not_null item, const MessageGroupId &groupId, - const MTPInputMedia &media, - bool silent) { + const MTPInputMedia &media) { const auto localId = item->fullId(); const auto failed = [this] { @@ -2865,6 +2875,13 @@ void ApiWrap::uploadAlbumMedia( if (!item) { failed(); } + if (const auto media = item->getMedia()) { + if (const auto photo = media->getPhoto()) { + photo->setWaitingForAlbum(); + } else if (const auto document = media->getDocument()) { + document->setWaitingForAlbum(); + } + } switch (result.type()) { case mtpc_messageMediaPhoto: { @@ -2883,7 +2900,7 @@ void ApiWrap::uploadAlbumMedia( MTP_inputPhoto(photo.vid, photo.vaccess_hash), data.has_caption() ? data.vcaption : MTP_string(QString()), data.has_ttl_seconds() ? data.vttl_seconds : MTPint()); - trySendAlbum(item, groupId, media, silent); + sendAlbumWithUploaded(item, groupId, media); } break; case mtpc_messageMediaDocument: { @@ -2902,7 +2919,7 @@ void ApiWrap::uploadAlbumMedia( MTP_inputDocument(document.vid, document.vaccess_hash), data.has_caption() ? data.vcaption : MTP_string(QString()), data.has_ttl_seconds() ? data.vttl_seconds : MTPint()); - trySendAlbum(item, groupId, media, silent); + sendAlbumWithUploaded(item, groupId, media); } break; } }).fail([=](const RPCError &error) { @@ -2910,40 +2927,6 @@ void ApiWrap::uploadAlbumMedia( }).send(); } -void ApiWrap::trySendAlbum( - not_null item, - const MessageGroupId &groupId, - const MTPInputMedia &media, - bool silent) { - const auto localId = item->fullId(); - const auto randomId = rand_value(); - App::historyRegRandom(randomId, localId); - - const auto medias = completeAlbum(localId, groupId, media, randomId); - if (medias.empty()) { - return; - } - - const auto history = item->history(); - const auto replyTo = item->replyToId(); - const auto flags = MTPmessages_SendMultiMedia::Flags(0) - | (replyTo - ? MTPmessages_SendMultiMedia::Flag::f_reply_to_msg_id - : MTPmessages_SendMultiMedia::Flag(0)) - | (IsSilentPost(item, silent) - ? MTPmessages_SendMultiMedia::Flag::f_silent - : MTPmessages_SendMultiMedia::Flag(0)); - history->sendRequestId = request(MTPmessages_SendMultiMedia( - MTP_flags(flags), - history->peer->input, - MTP_int(replyTo), - MTP_vector(medias) - )).done([=](const MTPUpdates &result) { applyUpdates(result); - }).fail([=](const RPCError &error) { sendMessageFail(error); - }).afterRequest(history->sendRequestId - ).send(); -} - void ApiWrap::sendMedia( not_null item, const MTPInputMedia &media, @@ -2951,6 +2934,14 @@ void ApiWrap::sendMedia( const auto randomId = rand_value(); App::historyRegRandom(randomId, item->fullId()); + sendMediaWithRandomId(item, media, silent, randomId); +} + +void ApiWrap::sendMediaWithRandomId( + not_null item, + const MTPInputMedia &media, + bool silent, + uint64 randomId) { const auto history = item->history(); const auto replyTo = item->replyToId(); const auto flags = MTPmessages_SendMedia::Flags(0) @@ -2973,11 +2964,14 @@ void ApiWrap::sendMedia( ).send(); } -QVector ApiWrap::completeAlbum( - FullMsgId localId, +void ApiWrap::sendAlbumWithUploaded( + not_null item, const MessageGroupId &groupId, - const MTPInputMedia &media, - uint64 randomId) { + const MTPInputMedia &media) { + const auto localId = item->fullId(); + const auto randomId = rand_value(); + App::historyRegRandom(randomId, localId); + const auto albumIt = _sendingAlbums.find(groupId.raw()); Assert(albumIt != _sendingAlbums.end()); const auto &album = albumIt->second; @@ -2990,15 +2984,79 @@ QVector ApiWrap::completeAlbum( Assert(!itemIt->media); itemIt->media = MTP_inputSingleMedia(media, MTP_long(randomId)); - auto result = QVector(); - result.reserve(album->items.size()); + sendAlbumIfReady(album.get()); +} + +void ApiWrap::sendAlbumWithCancelled( + not_null item, + const MessageGroupId &groupId) { + const auto localId = item->fullId(); + const auto albumIt = _sendingAlbums.find(groupId.raw()); + Assert(albumIt != _sendingAlbums.end()); + const auto &album = albumIt->second; + + const auto proj = [](const SendingAlbum::Item &item) { + return item.msgId; + }; + const auto itemIt = ranges::find(album->items, localId, proj); + Assert(itemIt != album->items.end()); + album->items.erase(itemIt); + + sendAlbumIfReady(album.get()); +} + +void ApiWrap::sendAlbumIfReady(not_null album) { + const auto groupId = album->groupId; + if (album->items.empty()) { + _sendingAlbums.remove(groupId); + return; + } + auto sample = (HistoryItem*)nullptr; + auto medias = QVector(); + medias.reserve(album->items.size()); for (const auto &item : album->items) { if (!item.media) { - return {}; + return; + } else if (!sample) { + sample = App::histItemById(item.msgId); } - result.push_back(*item.media); + medias.push_back(*item.media); } - return result; + if (!sample) { + _sendingAlbums.remove(groupId); + return; + } else if (medias.size() < 2) { + const auto &single = medias.front().c_inputSingleMedia(); + sendMediaWithRandomId( + sample, + single.vmedia, + album->silent, + single.vrandom_id.v); + _sendingAlbums.remove(groupId); + return; + } + const auto history = sample->history(); + const auto replyTo = sample->replyToId(); + const auto flags = MTPmessages_SendMultiMedia::Flags(0) + | (replyTo + ? MTPmessages_SendMultiMedia::Flag::f_reply_to_msg_id + : MTPmessages_SendMultiMedia::Flag(0)) + | (IsSilentPost(sample, album->silent) + ? MTPmessages_SendMultiMedia::Flag::f_silent + : MTPmessages_SendMultiMedia::Flag(0)); + history->sendRequestId = request(MTPmessages_SendMultiMedia( + MTP_flags(flags), + history->peer->input, + MTP_int(replyTo), + MTP_vector(medias) + )).done([=](const MTPUpdates &result) { + _sendingAlbums.remove(groupId); + applyUpdates(result); + }).fail([=](const RPCError &error) { + _sendingAlbums.remove(groupId); + sendMessageFail(error); + }).afterRequest(history->sendRequestId + ).send(); } void ApiWrap::readServerHistory(not_null history) { diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index b5c1df1b9..8e3ac88ec 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -215,6 +215,7 @@ public: const MTPInputFile &file, const base::optional &thumb, bool silent); + void cancelLocalItem(not_null item); ~ApiWrap(); @@ -317,22 +318,24 @@ private: void uploadAlbumMedia( not_null item, const MessageGroupId &groupId, - const MTPInputMedia &media, - bool silent); - void trySendAlbum( + const MTPInputMedia &media); + void sendAlbumWithUploaded( not_null item, const MessageGroupId &groupId, - const MTPInputMedia &media, - bool silent); - QVector completeAlbum( - FullMsgId localId, - const MessageGroupId &groupId, - const MTPInputMedia &media, - uint64 randomId); + const MTPInputMedia &media); + void sendAlbumWithCancelled( + not_null item, + const MessageGroupId &groupId); + void sendAlbumIfReady(not_null album); void sendMedia( not_null item, const MTPInputMedia &media, bool silent); + void sendMediaWithRandomId( + not_null item, + const MTPInputMedia &media, + bool silent, + uint64 randomId); not_null _session; mtpRequestId _changelogSubscription = 0; diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index 9d39b6333..8a544b17f 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -1375,17 +1375,24 @@ namespace { } PhotoData *photo(const PhotoId &photo) { - PhotosData::const_iterator i = ::photosData.constFind(photo); + auto i = ::photosData.constFind(photo); if (i == ::photosData.cend()) { i = ::photosData.insert(photo, new PhotoData(photo)); } return i.value(); } - PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const uint64 &access, int32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full) { + PhotoData *photoSet( + const PhotoId &photo, + PhotoData *convert, + const uint64 &access, + int32 date, + const ImagePtr &thumb, + const ImagePtr &medium, + const ImagePtr &full) { if (convert) { if (convert->id != photo) { - PhotosData::iterator i = ::photosData.find(convert->id); + const auto i = ::photosData.find(convert->id); if (i != ::photosData.cend() && i.value() == convert) { ::photosData.erase(i); } @@ -1400,9 +1407,9 @@ namespace { updateImage(convert->full, full); } } - PhotosData::const_iterator i = ::photosData.constFind(photo); + const auto i = ::photosData.constFind(photo); PhotoData *result; - LastPhotosMap::iterator inLastIter = lastPhotosMap.end(); + auto inLastIter = lastPhotosMap.end(); if (i == ::photosData.cend()) { if (convert) { result = convert; @@ -1436,27 +1443,39 @@ namespace { } DocumentData *document(const DocumentId &document) { - DocumentsData::const_iterator i = ::documentsData.constFind(document); + auto i = ::documentsData.constFind(document); if (i == ::documentsData.cend()) { i = ::documentsData.insert(document, DocumentData::create(document)); } return i.value(); } - DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const uint64 &access, int32 version, int32 date, const QVector &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size, const StorageImageLocation &thumbLocation) { + DocumentData *documentSet( + const DocumentId &document, + DocumentData *convert, + const uint64 &access, + int32 version, + int32 date, + const QVector &attributes, + const QString &mime, + const ImagePtr &thumb, + int32 dc, + int32 size, + const StorageImageLocation &thumbLocation) { bool versionChanged = false; bool sentSticker = false; if (convert) { - MediaKey oldKey = convert->mediaKey(); - bool idChanged = (convert->id != document); + const auto oldKey = convert->mediaKey(); + const auto idChanged = (convert->id != document); if (idChanged) { - DocumentsData::iterator i = ::documentsData.find(convert->id); + const auto i = ::documentsData.find(convert->id); if (i != ::documentsData.cend() && i.value() == convert) { ::documentsData.erase(i); } convert->id = document; convert->status = FileReady; + convert->uploadingData = nullptr; sentSticker = (convert->sticker() != 0); } if (date) { @@ -1474,7 +1493,7 @@ namespace { convert->sticker()->loc = thumbLocation; } - MediaKey newKey = convert->mediaKey(); + const auto newKey = convert->mediaKey(); if (idChanged) { if (convert->isVoiceMessage()) { Local::copyAudio(oldKey, newKey); @@ -1488,7 +1507,7 @@ namespace { Local::writeSavedGifs(); } } - DocumentsData::const_iterator i = ::documentsData.constFind(document); + const auto i = ::documentsData.constFind(document); DocumentData *result; if (i == ::documentsData.cend()) { if (convert) { @@ -1565,10 +1584,23 @@ namespace { return i.value(); } - WebPageData *webPageSet(const WebPageId &webPage, WebPageData *convert, const QString &type, const QString &url, const QString &displayUrl, const QString &siteName, const QString &title, const TextWithEntities &description, PhotoData *photo, DocumentData *document, int32 duration, const QString &author, int32 pendingTill) { + WebPageData *webPageSet( + const WebPageId &webPage, + WebPageData *convert, + const QString &type, + const QString &url, + const QString &displayUrl, + const QString &siteName, + const QString &title, + const TextWithEntities &description, + PhotoData *photo, + DocumentData *document, + int32 duration, + const QString &author, + int32 pendingTill) { if (convert) { if (convert->id != webPage) { - auto i = webPagesData.find(convert->id); + const auto i = webPagesData.find(convert->id); if (i != webPagesData.cend() && i.value() == convert) { webPagesData.erase(i); } @@ -1592,7 +1624,7 @@ namespace { if (App::main()) App::main()->webPageUpdated(convert); } } - auto i = webPagesData.constFind(webPage); + const auto i = webPagesData.constFind(webPage); WebPageData *result; if (i == webPagesData.cend()) { if (convert) { diff --git a/Telegram/SourceFiles/data/data_document.cpp b/Telegram/SourceFiles/data/data_document.cpp index ecb277461..a108f0d78 100644 --- a/Telegram/SourceFiles/data/data_document.cpp +++ b/Telegram/SourceFiles/data/data_document.cpp @@ -332,28 +332,15 @@ void DocumentOpenClickHandler::doOpen( } void DocumentOpenClickHandler::onClickImpl() const { - const auto item = context() - ? App::histItemById(context()) - : App::hoveredLinkItem() - ? App::hoveredLinkItem() - : App::contextItem() - ? App::contextItem() - : nullptr; - const auto action = document()->isVoiceMessage() + const auto data = document(); + const auto action = data->isVoiceMessage() ? ActionOnLoadNone : ActionOnLoadOpen; - doOpen(document(), item, action); + doOpen(data, getActionItem(), action); } void GifOpenClickHandler::onClickImpl() const { - const auto item = context() - ? App::histItemById(context()) - : App::hoveredLinkItem() - ? App::hoveredLinkItem() - : App::contextItem() - ? App::contextItem() - : nullptr; - doOpen(document(), item, ActionOnLoadPlayInline); + doOpen(document(), getActionItem(), ActionOnLoadPlayInline); } void DocumentSaveClickHandler::doSave( @@ -382,17 +369,13 @@ void DocumentSaveClickHandler::onClickImpl() const { } void DocumentCancelClickHandler::onClickImpl() const { - auto data = document(); + const auto data = document(); if (!data->date) return; if (data->uploading()) { - if (auto item = App::hoveredLinkItem() ? App::hoveredLinkItem() : (App::contextItem() ? App::contextItem() : nullptr)) { - if (auto media = item->getMedia()) { - if (media->getDocument() == data) { - App::contextItem(item); - App::main()->cancelUploadLayer(); - } - } + if (const auto item = App::histItemById(context())) { + App::contextItem(item); + App::main()->cancelUploadLayer(); } } else { data->cancel(); @@ -685,12 +668,19 @@ QString DocumentData::loadingFilePath() const { } bool DocumentData::displayLoading() const { - return loading() ? (!_loader->loadingLocal() || !_loader->autoLoading()) : uploading(); + return loading() + ? (!_loader->loadingLocal() || !_loader->autoLoading()) + : (uploading() && !waitingForAlbum()); } float64 DocumentData::progress() const { if (uploading()) { - return snap((size > 0) ? float64(uploadOffset) / size : 0., 0., 1.); + if (uploadingData->size > 0) { + const auto result = float64(uploadingData->offset) + / uploadingData->size; + return snap(result, 0., 1.); + } + return 0.; } return loading() ? _loader->currentProgress() : (loaded() ? 1. : 0.); } @@ -700,7 +690,17 @@ int32 DocumentData::loadOffset() const { } bool DocumentData::uploading() const { - return status == FileUploading; + return (uploadingData != nullptr); +} + +void DocumentData::setWaitingForAlbum() { + if (uploading()) { + uploadingData->waitingForAlbum = true; + } +} + +bool DocumentData::waitingForAlbum() const { + return uploading() && uploadingData->waitingForAlbum; } void DocumentData::save(const QString &toFile, ActionOnLoad action, const FullMsgId &actionMsgId, LoadFromCloudSetting fromCloud, bool autoLoading) { diff --git a/Telegram/SourceFiles/data/data_document.h b/Telegram/SourceFiles/data/data_document.h index da218e707..3cac5459d 100644 --- a/Telegram/SourceFiles/data/data_document.h +++ b/Telegram/SourceFiles/data/data_document.h @@ -125,6 +125,9 @@ public: int32 loadOffset() const; bool uploading() const; + void setWaitingForAlbum(); + bool waitingForAlbum() const; + QByteArray data() const; const FileLocation &location(bool check = false) const; void setLocation(const FileLocation &loc); @@ -241,7 +244,8 @@ public: int32 size = 0; FileStatus status = FileReady; - int32 uploadOffset = 0; + + std::unique_ptr uploadingData; int32 md5[8]; diff --git a/Telegram/SourceFiles/data/data_photo.cpp b/Telegram/SourceFiles/data/data_photo.cpp index 9e1498d18..65d1f4929 100644 --- a/Telegram/SourceFiles/data/data_photo.cpp +++ b/Telegram/SourceFiles/data/data_photo.cpp @@ -63,7 +63,9 @@ bool PhotoData::loading() const { } bool PhotoData::displayLoading() const { - return full->loading() ? full->displayLoading() : uploading(); + return full->loading() + ? full->displayLoading() + : (uploading() && !waitingForAlbum()); } void PhotoData::cancel() { @@ -91,12 +93,22 @@ float64 PhotoData::progress() const { return full->progress(); } +void PhotoData::setWaitingForAlbum() { + if (uploading()) { + uploadingData->waitingForAlbum = true; + } +} + +bool PhotoData::waitingForAlbum() const { + return uploading() && uploadingData->waitingForAlbum; +} + int32 PhotoData::loadOffset() const { return full->loadOffset(); } bool PhotoData::uploading() const { - return !!uploadingData; + return (uploadingData != nullptr); } void PhotoData::forget() { diff --git a/Telegram/SourceFiles/data/data_photo.h b/Telegram/SourceFiles/data/data_photo.h index 3c9a21262..985bda5d0 100644 --- a/Telegram/SourceFiles/data/data_photo.h +++ b/Telegram/SourceFiles/data/data_photo.h @@ -44,6 +44,9 @@ public: int32 loadOffset() const; bool uploading() const; + void setWaitingForAlbum(); + bool waitingForAlbum() const; + void forget(); ImagePtr makeReplyPreview(); @@ -57,13 +60,7 @@ public: PeerData *peer = nullptr; // for chat and channel photos connection // geo, caption - struct UploadingData { - UploadingData(int size) : size(size) { - } - int offset = 0; - int size = 0; - }; - std::unique_ptr uploadingData; + std::unique_ptr uploadingData; private: void notifyLayoutChanged() const; diff --git a/Telegram/SourceFiles/data/data_types.cpp b/Telegram/SourceFiles/data/data_types.cpp index d34c2bfbe..3a6ba46a5 100644 --- a/Telegram/SourceFiles/data/data_types.cpp +++ b/Telegram/SourceFiles/data/data_types.cpp @@ -53,3 +53,13 @@ void MessageCursor::applyTo(QTextEdit *edit) { scrollbar->setValue(scroll); } } + +HistoryItem *FileClickHandler::getActionItem() const { + return context() + ? App::histItemById(context()) + : App::hoveredLinkItem() + ? App::hoveredLinkItem() + : App::contextItem() + ? App::contextItem() + : nullptr; +} diff --git a/Telegram/SourceFiles/data/data_types.h b/Telegram/SourceFiles/data/data_types.h index ae72f0d8d..3fd1c94f6 100644 --- a/Telegram/SourceFiles/data/data_types.h +++ b/Telegram/SourceFiles/data/data_types.h @@ -20,6 +20,18 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org */ #pragma once +namespace Data { + +struct UploadState { + UploadState(int size) : size(size) { + } + int offset = 0; + int size = 0; + bool waitingForAlbum = false; +}; + +} // namespace Data + class PeerData; class UserData; class ChatData; @@ -241,7 +253,6 @@ enum LocationType { enum FileStatus { FileDownloadFailed = -2, FileUploadFailed = -1, - FileUploading = 0, FileReady = 1, }; @@ -404,6 +415,9 @@ public: return _context; } +protected: + HistoryItem *getActionItem() const; + private: FullMsgId _context; diff --git a/Telegram/SourceFiles/history/history.style b/Telegram/SourceFiles/history/history.style index 67a5f4eed..c00bcdb05 100644 --- a/Telegram/SourceFiles/history/history.style +++ b/Telegram/SourceFiles/history/history.style @@ -123,6 +123,8 @@ historyFileThumbCancel: icon {{ "history_file_cancel", historyFileThumbIconFg }} historyFileThumbCancelSelected: icon {{ "history_file_cancel", historyFileThumbIconFgSelected }}; historyFileThumbPlay: icon {{ "history_file_play", historyFileThumbIconFg }}; historyFileThumbPlaySelected: icon {{ "history_file_play", historyFileThumbIconFgSelected }}; +historyFileThumbWaiting: icon {{ "mediaview_save_check", historyFileThumbIconFg }}; +historyFileThumbWaitingSelected: icon {{ "mediaview_save_check", historyFileThumbIconFgSelected }}; historySendStateSpace: 24px; historySendStatePosition: point(-17px, -19px); diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index 0ed83adea..730f0a9cc 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -35,6 +35,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "storage/storage_facade.h" #include "storage/storage_shared_media.h" #include "auth_session.h" +#include "apiwrap.h" #include "media/media_audio.h" #include "messenger.h" #include "mainwindow.h" @@ -294,18 +295,20 @@ void HistoryItem::destroy() { // All this must be done for all items manually in History::clear(false)! eraseFromUnreadMentions(); if (IsServerMsgId(id)) { - if (auto types = sharedMediaTypes()) { + if (const auto types = sharedMediaTypes()) { Auth().storage().remove(Storage::SharedMediaRemoveOne( history()->peer->id, types, id)); } + } else { + Auth().api().cancelLocalItem(this); } auto wasAtBottom = history()->loadedAtBottom(); _history->removeNotification(this); detach(); - if (auto channel = history()->peer->asChannel()) { + if (const auto channel = history()->peer->asChannel()) { if (channel->pinnedMessageId() == id) { channel->clearPinnedMessage(); } diff --git a/Telegram/SourceFiles/history/history_media_types.cpp b/Telegram/SourceFiles/history/history_media_types.cpp index a6f46ab40..010a8e016 100644 --- a/Telegram/SourceFiles/history/history_media_types.cpp +++ b/Telegram/SourceFiles/history/history_media_types.cpp @@ -442,7 +442,9 @@ void HistoryPhoto::draw(Painter &p, const QRect &r, TextSelection selection, Tim p.drawPixmap(rthumb.topLeft(), pix); } if (radial || (!loaded && !_data->loading())) { - float64 radialOpacity = (radial && loaded && !_data->uploading()) ? _animation->radial.opacity() : 1; + const auto radialOpacity = (radial && loaded && !_data->uploading()) + ? _animation->radial.opacity() : + 1.; QRect inner(rthumb.x() + (rthumb.width() - st::msgFileSize) / 2, rthumb.y() + (rthumb.height() - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize); p.setPen(Qt::NoPen); if (selected) { @@ -600,7 +602,10 @@ void HistoryPhoto::drawGrouped( App::complexOverlayRect(p, geometry, roundRadius, corners); } - if (radial || (!loaded && !_data->loading())) { + const auto displayState = radial + || (!loaded && !_data->loading()) + || _data->waitingForAlbum(); + if (displayState) { const auto radialOpacity = (radial && loaded && !_data->uploading()) ? _animation->radial.opacity() : 1.; @@ -629,8 +634,10 @@ void HistoryPhoto::drawGrouped( } p.setOpacity(radialOpacity); - auto icon = ([radial, this, selected]() -> const style::icon*{ - if (radial || _data->loading()) { + auto icon = [&]() -> const style::icon* { + if (_data->waitingForAlbum()) { + return &(selected ? st::historyFileThumbWaitingSelected : st::historyFileThumbWaiting); + } else if (radial || _data->loading()) { auto delayed = _data->full->toDelayedStorageImage(); if (!delayed || !delayed->location().isNull()) { return &(selected ? st::historyFileThumbCancelSelected : st::historyFileThumbCancel); @@ -638,7 +645,7 @@ void HistoryPhoto::drawGrouped( return nullptr; } return &(selected ? st::historyFileThumbDownloadSelected : st::historyFileThumbDownload); - })(); + }(); if (icon) { icon->paintInCenter(p, inner); } @@ -673,6 +680,19 @@ HistoryTextState HistoryPhoto::getStateGrouped( : _savel); } +float64 HistoryPhoto::dataProgress() const { + return _data->progress(); +} + +bool HistoryPhoto::dataFinished() const { + return !_data->loading() + && (!_data->uploading() || _data->waitingForAlbum()); +} + +bool HistoryPhoto::dataLoaded() const { + return _data->loaded(); +} + void HistoryPhoto::validateGroupedCache( const QRect &geometry, RectParts corners, @@ -1158,8 +1178,10 @@ void HistoryVideo::drawGrouped( } p.setOpacity(radialOpacity); - auto icon = ([this, radial, selected, loaded]() -> const style::icon * { - if (loaded && !radial) { + auto icon = [&]() -> const style::icon * { + if (_data->waitingForAlbum()) { + return &(selected ? st::historyFileThumbWaitingSelected : st::historyFileThumbWaiting); + } else if (loaded && !radial) { return &(selected ? st::historyFileThumbPlaySelected : st::historyFileThumbPlay); } else if (radial || _data->loading()) { if (_parent->id > 0 || _data->uploading()) { @@ -1168,7 +1190,7 @@ void HistoryVideo::drawGrouped( return nullptr; } return &(selected ? st::historyFileThumbDownloadSelected : st::historyFileThumbDownload); - })(); + }(); if (icon) { icon->paintInCenter(p, inner); } @@ -1199,6 +1221,19 @@ HistoryTextState HistoryVideo::getStateGrouped( : _savel); } +float64 HistoryVideo::dataProgress() const { + return _data->progress(); +} + +bool HistoryVideo::dataFinished() const { + return !_data->loading() + && (!_data->uploading() || _data->waitingForAlbum()); +} + +bool HistoryVideo::dataLoaded() const { + return _data->loaded(); +} + void HistoryVideo::validateGroupedCache( const QRect &geometry, RectParts corners, @@ -1278,8 +1313,8 @@ void HistoryVideo::updateStatusText() const { int32 statusSize = 0, realDuration = 0; if (_data->status == FileDownloadFailed || _data->status == FileUploadFailed) { statusSize = FileStatusSizeFailed; - } else if (_data->status == FileUploading) { - statusSize = _data->uploadOffset; + } else if (_data->uploading()) { + statusSize = _data->uploadingData->offset; } else if (_data->loading()) { statusSize = _data->loadOffset(); } else if (_data->loaded()) { @@ -1374,6 +1409,18 @@ HistoryDocument::HistoryDocument( } } +float64 HistoryDocument::dataProgress() const { + return _data->progress(); +} + +bool HistoryDocument::dataFinished() const { + return !_data->loading() && !_data->uploading(); +} + +bool HistoryDocument::dataLoaded() const { + return _data->loaded(); +} + void HistoryDocument::createComponents(bool caption) { uint64 mask = 0; if (_data->isVoiceMessage()) { @@ -1573,7 +1620,9 @@ void HistoryDocument::draw(Painter &p, const QRect &r, TextSelection selection, } if (_data->status != FileUploadFailed) { - const ClickHandlerPtr &lnk((_data->loading() || _data->status == FileUploading) ? thumbed->_linkcancell : thumbed->_linksavel); + const auto &lnk = (_data->loading() || _data->uploading()) + ? thumbed->_linkcancell + : thumbed->_linksavel; bool over = ClickHandler::showAsActive(lnk); p.setFont(over ? st::semiboldFont->underline() : st::semiboldFont); p.setPen(outbg ? (selected ? st::msgFileThumbLinkOutFgSelected : st::msgFileThumbLinkOutFg) : (selected ? st::msgFileThumbLinkInFgSelected : st::msgFileThumbLinkInFg)); @@ -1766,7 +1815,9 @@ HistoryTextState HistoryDocument::getState(QPoint point, HistoryStateRequest req if (_data->status != FileUploadFailed) { if (rtlrect(nameleft, linktop, thumbed->_linkw, st::semiboldFont->height, _width).contains(point)) { - result.link = (_data->loading() || _data->uploading()) ? thumbed->_linkcancell : thumbed->_linksavel; + result.link = (_data->loading() || _data->uploading()) + ? thumbed->_linkcancell + : thumbed->_linksavel; return result; } } @@ -1952,8 +2003,8 @@ bool HistoryDocument::updateStatusText() const { int32 statusSize = 0, realDuration = 0; if (_data->status == FileDownloadFailed || _data->status == FileUploadFailed) { statusSize = FileStatusSizeFailed; - } else if (_data->status == FileUploading) { - statusSize = _data->uploadOffset; + } else if (_data->uploading()) { + statusSize = _data->uploadingData->offset; } else if (_data->loading()) { statusSize = _data->loadOffset(); } else if (_data->loaded()) { @@ -2769,8 +2820,8 @@ void HistoryGif::updateStatusText() const { int32 statusSize = 0, realDuration = 0; if (_data->status == FileDownloadFailed || _data->status == FileUploadFailed) { statusSize = FileStatusSizeFailed; - } else if (_data->status == FileUploading) { - statusSize = _data->uploadOffset; + } else if (_data->uploading()) { + statusSize = _data->uploadingData->offset; } else if (_data->loading()) { statusSize = _data->loadOffset(); } else if (_data->loaded()) { @@ -2924,15 +2975,19 @@ HistoryGif::~HistoryGif() { } float64 HistoryGif::dataProgress() const { - return (_data->uploading() || !_parent || _parent->id > 0) ? _data->progress() : 0; + return (_data->uploading() || _parent->id > 0) + ? _data->progress() + : 0; } bool HistoryGif::dataFinished() const { - return (!_parent || _parent->id > 0) ? (!_data->loading() && !_data->uploading()) : false; + return (_parent->id > 0) + ? (!_data->loading() && !_data->uploading()) + : false; } bool HistoryGif::dataLoaded() const { - return (!_parent || _parent->id > 0) ? _data->loaded() : false; + return (_parent->id > 0) ? _data->loaded() : false; } HistorySticker::HistorySticker( diff --git a/Telegram/SourceFiles/history/history_media_types.h b/Telegram/SourceFiles/history/history_media_types.h index 0eec99d37..9b3e6a19e 100644 --- a/Telegram/SourceFiles/history/history_media_types.h +++ b/Telegram/SourceFiles/history/history_media_types.h @@ -263,15 +263,9 @@ public: } protected: - float64 dataProgress() const override { - return _data->progress(); - } - bool dataFinished() const override { - return !_data->loading() && !_data->uploading(); - } - bool dataLoaded() const override { - return _data->loaded(); - } + float64 dataProgress() const override; + bool dataFinished() const override; + bool dataLoaded() const override; private: void validateGroupedCache( @@ -383,15 +377,9 @@ public: } protected: - float64 dataProgress() const override { - return _data->progress(); - } - bool dataFinished() const override { - return !_data->loading() && !_data->uploading(); - } - bool dataLoaded() const override { - return _data->loaded(); - } + float64 dataProgress() const override; + bool dataFinished() const override; + bool dataLoaded() const override; private: void validateGroupedCache( @@ -493,15 +481,9 @@ public: void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) override; protected: - float64 dataProgress() const override { - return _data->progress(); - } - bool dataFinished() const override { - return !_data->loading() && !_data->uploading(); - } - bool dataLoaded() const override { - return _data->loaded(); - } + float64 dataProgress() const override; + bool dataFinished() const override; + bool dataLoaded() const override; private: void createComponents(bool caption); diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 29b9f1e23..a19184470 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -4347,10 +4347,13 @@ void HistoryWidget::onDocumentProgress(const FullMsgId &newId) { const auto sendAction = (document && document->isVoiceMessage()) ? SendAction::Type::UploadVoice : SendAction::Type::UploadFile; + const auto progress = (document && document->uploading()) + ? document->uploadingData->offset + : 0; updateSendAction( item->history(), sendAction, - document ? document->uploadOffset : 0); + progress); Auth().data().requestItemRepaint(item); } } diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp index 85823370e..7cc8413f5 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp @@ -850,8 +850,8 @@ bool File::updateStatusText() const { DocumentData *document = getShownDocument(); if (document->status == FileDownloadFailed || document->status == FileUploadFailed) { statusSize = FileStatusSizeFailed; - } else if (document->status == FileUploading) { - statusSize = document->uploadOffset; + } else if (document->uploading()) { + statusSize = document->uploadingData->offset; } else if (document->loading()) { statusSize = document->loadOffset(); } else if (document->loaded()) { diff --git a/Telegram/SourceFiles/overview/overview_layout.cpp b/Telegram/SourceFiles/overview/overview_layout.cpp index 67f9cef2c..07c79e540 100644 --- a/Telegram/SourceFiles/overview/overview_layout.cpp +++ b/Telegram/SourceFiles/overview/overview_layout.cpp @@ -524,8 +524,8 @@ void Video::updateStatusText() { int statusSize = 0; if (_data->status == FileDownloadFailed || _data->status == FileUploadFailed) { statusSize = FileStatusSizeFailed; - } else if (_data->status == FileUploading) { - statusSize = _data->uploadOffset; + } else if (_data->uploading()) { + statusSize = _data->uploadingData->offset; } else if (_data->loading()) { statusSize = _data->loadOffset(); } else if (_data->loaded()) { @@ -695,7 +695,7 @@ HistoryTextState Voice::getState( if (inner.contains(point)) { const auto link = loaded ? _openl - : (_data->loading() || _data->status == FileUploading) + : (_data->loading() || _data->uploading()) ? _cancell : _openl; return { parent(), link }; @@ -1023,7 +1023,7 @@ HistoryTextState Document::getState( if (inner.contains(point)) { const auto link = loaded ? _openl - : (_data->loading() || _data->status == FileUploading) + : (_data->loading() || _data->uploading()) ? _cancell : _openl; return { parent(), link }; @@ -1057,7 +1057,7 @@ HistoryTextState Document::getState( if (rthumb.contains(point)) { const auto link = loaded ? _openl - : (_data->loading() || _data->status == FileUploading) + : (_data->loading() || _data->uploading()) ? _cancell : _savel; return { parent(), link }; @@ -1133,8 +1133,8 @@ bool Document::updateStatusText() { int32 statusSize = 0, realDuration = 0; if (_data->status == FileDownloadFailed || _data->status == FileUploadFailed) { statusSize = FileStatusSizeFailed; - } else if (_data->status == FileUploading) { - statusSize = _data->uploadOffset; + } else if (_data->uploading()) { + statusSize = _data->uploadingData->offset; } else if (_data->loading()) { statusSize = _data->loadOffset(); } else if (_data->loaded()) { diff --git a/Telegram/SourceFiles/storage/file_upload.cpp b/Telegram/SourceFiles/storage/file_upload.cpp index 65404231c..16c2e3219 100644 --- a/Telegram/SourceFiles/storage/file_upload.cpp +++ b/Telegram/SourceFiles/storage/file_upload.cpp @@ -137,7 +137,6 @@ void Uploader::uploadMedia(const FullMsgId &msgId, const SendMediaReady &media) } else { document = App::feedDocument(media.document, media.photoThumbs.begin().value()); } - document->status = FileUploading; if (!media.data.isEmpty()) { document->setData(media.data); } @@ -154,10 +153,10 @@ void Uploader::upload( const std::shared_ptr &file) { if (file->type == SendMediaType::Photo) { auto photo = App::feedPhoto(file->photo, file->photoThumbs); - photo->uploadingData = std::make_unique(file->partssize); + photo->uploadingData = std::make_unique(file->partssize); } else if (file->type == SendMediaType::File || file->type == SendMediaType::Audio) { auto document = file->thumb.isNull() ? App::feedDocument(file->document) : App::feedDocument(file->document, file->thumb); - document->status = FileUploading; + document->uploadingData = std::make_unique(document->size); if (!file->content.isEmpty()) { document->setData(file->content); } @@ -176,7 +175,7 @@ void Uploader::currentFailed() { emit photoFailed(j->first); } else if (j->second.type() == SendMediaType::File) { const auto document = App::document(j->second.id()); - if (document->status == FileUploading) { + if (document->uploading()) { document->status = FileUploadFailed; } emit documentFailed(j->first); @@ -477,10 +476,9 @@ void Uploader::partLoaded(const MTPBool &result, mtpRequestId requestId) { if (document->uploading()) { const auto doneParts = file.docSentParts - int(docRequestsSent.size()); - document->uploadOffset = doneParts * file.docPartSize; - if (document->uploadOffset > document->size) { - document->uploadOffset = document->size; - } + document->uploadingData->offset = std::max( + document->uploadingData->size, + doneParts * file.docPartSize); } emit documentProgress(fullId); } diff --git a/Telegram/SourceFiles/storage/localimageloader.h b/Telegram/SourceFiles/storage/localimageloader.h index d9c547370..b90d643c2 100644 --- a/Telegram/SourceFiles/storage/localimageloader.h +++ b/Telegram/SourceFiles/storage/localimageloader.h @@ -180,8 +180,9 @@ struct SendingAlbum { SendingAlbum(); - uint64 groupId; + uint64 groupId = 0; std::vector items; + bool silent = false; };