Fix finalizing media in non-active account.

This commit is contained in:
John Preston 2020-07-06 13:58:18 +04:00
parent 000a7ae28b
commit 2f5cb33bf2
15 changed files with 396 additions and 304 deletions

View File

@ -215,6 +215,8 @@ PRIVATE
api/api_hash.h
api/api_self_destruct.cpp
api/api_self_destruct.h
api/api_send_progress.cpp
api/api_send_progress.h
api/api_sending.cpp
api/api_sending.h
api/api_sensitive_content.cpp

View File

@ -0,0 +1,105 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "api/api_send_progress.h"
#include "main/main_session.h"
#include "history/history.h"
#include "data/data_peer.h"
#include "apiwrap.h"
namespace Api {
namespace {
constexpr auto kCancelTypingActionTimeout = crl::time(5000);
} // namespace
SendProgressManager::SendProgressManager(not_null<Main::Session*> session)
: _session(session)
, _stopTypingTimer([=] { cancelTyping(base::take(_stopTypingHistory)); }) {
}
void SendProgressManager::cancel(
not_null<History*> history,
SendProgressType type) {
const auto i = _requests.find({ history, type });
if (i != _requests.end()) {
_session->api().request(i->second).cancel();
_requests.erase(i);
}
}
void SendProgressManager::cancelTyping(not_null<History*> history) {
_stopTypingTimer.cancel();
cancel(history, SendProgressType::Typing);
}
void SendProgressManager::update(
not_null<History*> history,
SendProgressType type,
int32 progress) {
const auto peer = history->peer;
if (peer->isSelf() || (peer->isChannel() && !peer->isMegagroup())) {
return;
}
const auto doing = (progress >= 0);
if (history->mySendActionUpdated(type, doing)) {
cancel(history, type);
if (doing) {
send(history, type, progress);
}
}
}
void SendProgressManager::send(
not_null<History*> history,
SendProgressType type,
int32 progress) {
using Type = SendProgressType;
MTPsendMessageAction action;
switch (type) {
case Type::Typing: action = MTP_sendMessageTypingAction(); break;
case Type::RecordVideo: action = MTP_sendMessageRecordVideoAction(); break;
case Type::UploadVideo: action = MTP_sendMessageUploadVideoAction(MTP_int(progress)); break;
case Type::RecordVoice: action = MTP_sendMessageRecordAudioAction(); break;
case Type::UploadVoice: action = MTP_sendMessageUploadAudioAction(MTP_int(progress)); break;
case Type::RecordRound: action = MTP_sendMessageRecordRoundAction(); break;
case Type::UploadRound: action = MTP_sendMessageUploadRoundAction(MTP_int(progress)); break;
case Type::UploadPhoto: action = MTP_sendMessageUploadPhotoAction(MTP_int(progress)); break;
case Type::UploadFile: action = MTP_sendMessageUploadDocumentAction(MTP_int(progress)); break;
case Type::ChooseLocation: action = MTP_sendMessageGeoLocationAction(); break;
case Type::ChooseContact: action = MTP_sendMessageChooseContactAction(); break;
case Type::PlayGame: action = MTP_sendMessageGamePlayAction(); break;
}
const auto requestId = _session->api().request(MTPmessages_SetTyping(
history->peer->input,
action
)).done([=](const MTPBool &result, mtpRequestId requestId) {
done(result, requestId);
}).send();
_requests.emplace(Key{ history, type }, requestId);
if (type == Type::Typing) {
_stopTypingHistory = history;
_stopTypingTimer.callOnce(kCancelTypingActionTimeout);
}
}
void SendProgressManager::done(
const MTPBool &result,
mtpRequestId requestId) {
for (auto i = _requests.begin(), e = _requests.end(); i != e; ++i) {
if (i->second == requestId) {
_requests.erase(i);
break;
}
}
}
} // namespace Api

View File

@ -0,0 +1,88 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "api/api_common.h"
#include "base/timer.h"
class History;
namespace Main {
class Session;
} // namespace Main
namespace Api {
enum class SendProgressType {
Typing,
RecordVideo,
UploadVideo,
RecordVoice,
UploadVoice,
RecordRound,
UploadRound,
UploadPhoto,
UploadFile,
ChooseLocation,
ChooseContact,
PlayGame,
};
struct SendProgress {
SendProgress(
SendProgressType type,
crl::time until,
int progress = 0)
: type(type)
, until(until)
, progress(progress) {
}
SendProgressType type = SendProgressType::Typing;
crl::time until = 0;
int progress = 0;
};
class SendProgressManager final {
public:
SendProgressManager(not_null<Main::Session*> session);
void update(
not_null<History*> history,
SendProgressType type,
int32 progress = 0);
void cancel(
not_null<History*> history,
SendProgressType type);
void cancelTyping(not_null<History*> history);
private:
struct Key {
not_null<History*> history;
SendProgressType type = SendProgressType();
inline bool operator<(const Key &other) const {
return (history < other.history)
|| (history == other.history && type < other.type);
}
};
void send(
not_null<History*> history,
SendProgressType type,
int32 progress);
void done(const MTPBool &result, mtpRequestId requestId);
const not_null<Main::Session*> _session;
base::flat_map<Key, mtpRequestId> _requests;
base::Timer _stopTypingTimer;
History *_stopTypingHistory = nullptr;
};
} // namespace Api

View File

@ -15,6 +15,7 @@ struct FileLoadResult;
namespace Api {
struct MessageToSend;
struct SendAction;
void SendExistingDocument(
Api::MessageToSend &&message,

View File

@ -422,35 +422,6 @@ inline bool operator==(
&& (a.scroll == b.scroll);
}
struct SendAction {
enum class Type {
Typing,
RecordVideo,
UploadVideo,
RecordVoice,
UploadVoice,
RecordRound,
UploadRound,
UploadPhoto,
UploadFile,
ChooseLocation,
ChooseContact,
PlayGame,
};
SendAction(
Type type,
crl::time until,
int progress = 0)
: type(type)
, until(until)
, progress(progress) {
}
Type type = Type::Typing;
crl::time until = 0;
int progress = 0;
};
class FileClickHandler : public LeftButtonClickHandler {
public:
FileClickHandler(

View File

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "history/history.h"
#include "api/api_send_progress.h"
#include "history/view/history_view_element.h"
#include "history/history_message.h"
#include "history/history_service.h"
@ -357,7 +358,7 @@ bool History::updateSendActionNeedsAnimating(
return false;
}
using Type = SendAction::Type;
using Type = Api::SendProgressType;
if (action.type() == mtpc_sendMessageCancelAction) {
clearSendAction(user);
return false;
@ -420,7 +421,7 @@ bool History::updateSendActionNeedsAnimating(
return updateSendActionNeedsAnimating(now, true);
}
bool History::mySendActionUpdated(SendAction::Type type, bool doing) {
bool History::mySendActionUpdated(Api::SendProgressType type, bool doing) {
const auto now = crl::now();
const auto i = _mySendActions.find(type);
if (doing) {
@ -508,7 +509,7 @@ bool History::updateSendActionNeedsAnimating(crl::time now, bool force) {
begin(_typing)->first->firstName);
} else if (!_sendActions.empty()) {
// Handles all actions except game playing.
using Type = SendAction::Type;
using Type = Api::SendProgressType;
auto sendActionString = [](Type type, const QString &name) -> QString {
switch (type) {
case Type::RecordVideo: return name.isEmpty() ? tr::lng_send_action_record_video(tr::now) : tr::lng_user_action_record_video(tr::now, lt_user, name);
@ -562,7 +563,7 @@ bool History::updateSendActionNeedsAnimating(crl::time now, bool force) {
}
}
if (typingCount > 0) {
_sendActionAnimation.start(SendAction::Type::Typing);
_sendActionAnimation.start(Api::SendProgressType::Typing);
} else if (newTypingString.isEmpty()) {
_sendActionAnimation.stop();
}

View File

@ -23,6 +23,11 @@ class HistoryItem;
class HistoryMessage;
class HistoryService;
namespace Api {
enum class SendProgressType;
struct SendProgress;
} // namespace Api
namespace Main {
class Session;
} // namespace Main
@ -266,7 +271,7 @@ public:
bool hasPendingResizedItems() const;
void setHasPendingResizedItems();
bool mySendActionUpdated(SendAction::Type type, bool doing);
bool mySendActionUpdated(Api::SendProgressType type, bool doing);
bool paintSendAction(
Painter &p,
int x,
@ -573,11 +578,11 @@ private:
QString _topPromotedType;
base::flat_map<not_null<UserData*>, crl::time> _typing;
base::flat_map<not_null<UserData*>, SendAction> _sendActions;
base::flat_map<not_null<UserData*>, Api::SendProgress> _sendActions;
QString _sendActionString;
Ui::Text::String _sendActionText;
Ui::SendActionAnimation _sendActionAnimation;
base::flat_map<SendAction::Type, crl::time> _mySendActions;
base::flat_map<Api::SendProgressType, crl::time> _mySendActions;
std::deque<not_null<HistoryItem*>> _notifications;

View File

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_sending.h"
#include "api/api_text_entities.h"
#include "api/api_send_progress.h"
#include "boxes/confirm_box.h"
#include "boxes/send_files_box.h"
#include "boxes/share_box.h"
@ -123,7 +124,6 @@ constexpr auto kSkipRepaintWhileScrollMs = 100;
constexpr auto kShowMembersDropdownTimeoutMs = 300;
constexpr auto kDisplayEditTimeWarningMs = 300 * 1000;
constexpr auto kFullDayInMs = 86400 * 1000;
constexpr auto kCancelTypingActionTimeout = crl::time(5000);
constexpr auto kSaveDraftTimeout = 1000;
constexpr auto kSaveDraftAnywayTimeout = 5000;
constexpr auto kSaveCloudDraftIdleTimeout = 14000;
@ -299,7 +299,6 @@ HistoryWidget::HistoryWidget(
, _attachDragState(DragState::None)
, _attachDragDocument(this)
, _attachDragPhoto(this)
, _sendActionStopTimer([this] { cancelTypingAction(); })
, _topShadow(this) {
setAcceptDrops(true);
@ -737,7 +736,6 @@ HistoryWidget::HistoryWidget(
}
}, lifetime());
subscribeToUploader();
setupScheduledToggle();
orderWidgets();
setupShortcuts();
@ -1247,7 +1245,9 @@ void HistoryWidget::onTextChange() {
if (!_inlineBot
&& !_editMsgId
&& (_textUpdateEvents & TextUpdateEvent::SendTyping)) {
updateSendAction(_history, SendAction::Type::Typing);
session().sendProgressManager().update(
_history,
Api::SendProgressType::Typing);
}
}
@ -1390,77 +1390,6 @@ void HistoryWidget::writeDrafts(Data::Draft **localDraft, Data::Draft **editDraf
}
}
void HistoryWidget::cancelSendAction(
not_null<History*> history,
SendAction::Type type) {
const auto i = _sendActionRequests.find({ history, type });
if (i != _sendActionRequests.end()) {
_api.request(i->second).cancel();
_sendActionRequests.erase(i);
}
}
void HistoryWidget::cancelTypingAction() {
if (_history) {
cancelSendAction(_history, SendAction::Type::Typing);
}
_sendActionStopTimer.cancel();
}
void HistoryWidget::updateSendAction(
not_null<History*> history,
SendAction::Type type,
int32 progress) {
const auto peer = history->peer;
if (peer->isSelf() || (peer->isChannel() && !peer->isMegagroup())) {
return;
}
const auto doing = (progress >= 0);
if (history->mySendActionUpdated(type, doing)) {
cancelSendAction(history, type);
if (doing) {
using Type = SendAction::Type;
MTPsendMessageAction action;
switch (type) {
case Type::Typing: action = MTP_sendMessageTypingAction(); break;
case Type::RecordVideo: action = MTP_sendMessageRecordVideoAction(); break;
case Type::UploadVideo: action = MTP_sendMessageUploadVideoAction(MTP_int(progress)); break;
case Type::RecordVoice: action = MTP_sendMessageRecordAudioAction(); break;
case Type::UploadVoice: action = MTP_sendMessageUploadAudioAction(MTP_int(progress)); break;
case Type::RecordRound: action = MTP_sendMessageRecordRoundAction(); break;
case Type::UploadRound: action = MTP_sendMessageUploadRoundAction(MTP_int(progress)); break;
case Type::UploadPhoto: action = MTP_sendMessageUploadPhotoAction(MTP_int(progress)); break;
case Type::UploadFile: action = MTP_sendMessageUploadDocumentAction(MTP_int(progress)); break;
case Type::ChooseLocation: action = MTP_sendMessageGeoLocationAction(); break;
case Type::ChooseContact: action = MTP_sendMessageChooseContactAction(); break;
case Type::PlayGame: action = MTP_sendMessageGamePlayAction(); break;
}
const auto requestId = _api.request(MTPmessages_SetTyping(
peer->input,
action
)).done([=](const MTPBool &result, mtpRequestId requestId) {
sendActionDone(result, requestId);
}).send();
_sendActionRequests.emplace(std::pair(history, type), requestId);
if (type == Type::Typing) {
_sendActionStopTimer.callOnce(kCancelTypingActionTimeout);
}
}
}
}
void HistoryWidget::sendActionDone(
const MTPBool &result,
mtpRequestId requestId) {
for (auto i = _sendActionRequests.begin(), e = _sendActionRequests.end(); i != e; ++i) {
if (i->second == requestId) {
_sendActionRequests.erase(i);
break;
}
}
}
void HistoryWidget::activate() {
if (_history) {
if (!_historyInited) {
@ -1515,7 +1444,9 @@ void HistoryWidget::onRecordUpdate(quint16 level, qint32 samples) {
Core::App().updateNonIdle();
updateField();
if (_history) {
updateSendAction(_history, SendAction::Type::RecordVoice);
session().sendProgressManager().update(
_history,
Api::SendProgressType::RecordVoice);
}
}
@ -1795,9 +1726,12 @@ void HistoryWidget::showHistory(
}
return;
}
updateSendAction(_history, SendAction::Type::Typing, -1);
session().sendProgressManager().update(
_history,
Api::SendProgressType::Typing,
-1);
session().data().histories().sendPendingReadInbox(_history);
cancelTypingAction();
session().sendProgressManager().cancelTyping(_history);
}
clearReplyReturns();
@ -3588,7 +3522,10 @@ void HistoryWidget::stopRecording(bool send) {
_recording = false;
_recordingSamples = 0;
if (_history) {
updateSendAction(_history, SendAction::Type::RecordVoice, -1);
session().sendProgressManager().update(
_history,
Api::SendProgressType::RecordVoice,
-1);
}
updateControlsVisibility();
@ -3689,22 +3626,13 @@ void HistoryWidget::app_sendBotCallback(
flags |= MTPmessages_GetBotCallbackAnswer::Flag::f_data;
sendData = button->data;
}
const auto weak = Ui::MakeWeak(this);
button->requestId = session().api().request(MTPmessages_GetBotCallbackAnswer(
MTP_flags(flags),
_peer->input,
MTP_int(msg->id),
MTP_bytes(sendData)
)).done([info, weak](const MTPmessages_BotCallbackAnswer &result, mtpRequestId requestId) {
)).done([info](const MTPmessages_BotCallbackAnswer &result, mtpRequestId requestId) {
BotCallbackDone(info, result, requestId);
result.match([&](const MTPDmessages_botCallbackAnswer &data) {
const auto item = info.session->data().message(info.msgId);
if (!data.vmessage() && data.vurl() && info.game && item) {
if (const auto strong = weak.data()) {
strong->updateSendAction(item->history(), SendAction::Type::PlayGame);
}
}
});
}).fail([info](const RPCError &error, mtpRequestId requestId) {
BotCallbackFail(info, error, requestId);
}).send();
@ -3750,6 +3678,13 @@ void HistoryWidget::BotCallbackDone(
UrlClickHandler::Open(link);
}
}
if (const auto item = info.session->data().message(info.msgId)) {
if (!data.vmessage() && data.vurl() && info.game) {
info.session->sendProgressManager().update(
item->history(),
Api::SendProgressType::PlayGame);
}
}
});
}
@ -4654,144 +4589,6 @@ void HistoryWidget::uploadFile(
session().api().sendFile(fileContent, type, action);
}
void HistoryWidget::subscribeToUploader() {
using namespace Storage;
session().uploader().photoReady(
) | rpl::start_with_next([=](const UploadedPhoto &data) {
if (data.edit) {
session().api().editUploadedFile(
data.fullId,
data.file,
std::nullopt,
data.options,
false);
} else {
session().api().sendUploadedPhoto(
data.fullId,
data.file,
data.options);
}
}, lifetime());
session().uploader().photoProgress(
) | rpl::start_with_next([=](const FullMsgId &fullId) {
photoProgress(fullId);
}, lifetime());
session().uploader().photoFailed(
) | rpl::start_with_next([=](const FullMsgId &fullId) {
photoFailed(fullId);
}, lifetime());
session().uploader().documentReady(
) | rpl::start_with_next([=](const UploadedDocument &data) {
if (data.edit) {
documentEdited(data.fullId, data.options, data.file);
} else {
documentUploaded(data.fullId, data.options, data.file);
}
}, lifetime());
session().uploader().thumbDocumentReady(
) | rpl::start_with_next([=](const UploadedThumbDocument &data) {
thumbDocumentUploaded(
data.fullId,
data.options,
data.file,
data.thumb,
data.edit);
}, lifetime());
session().uploader().documentProgress(
) | rpl::start_with_next([=](const FullMsgId &fullId) {
documentProgress(fullId);
}, lifetime());
session().uploader().documentFailed(
) | rpl::start_with_next([=](const FullMsgId &fullId) {
documentFailed(fullId);
}, lifetime());
}
void HistoryWidget::documentUploaded(
const FullMsgId &newId,
Api::SendOptions options,
const MTPInputFile &file) {
session().api().sendUploadedDocument(newId, file, std::nullopt, options);
}
void HistoryWidget::documentEdited(
const FullMsgId &newId,
Api::SendOptions options,
const MTPInputFile &file) {
session().api().editUploadedFile(newId, file, std::nullopt, options, true);
}
void HistoryWidget::thumbDocumentUploaded(
const FullMsgId &newId,
Api::SendOptions options,
const MTPInputFile &file,
const MTPInputFile &thumb,
bool edit) {
if (edit) {
session().api().editUploadedFile(newId, file, thumb, options, true);
} else {
session().api().sendUploadedDocument(newId, file, thumb, options);
}
}
void HistoryWidget::photoProgress(const FullMsgId &newId) {
if (const auto item = session().data().message(newId)) {
const auto photo = item->media()
? item->media()->photo()
: nullptr;
updateSendAction(item->history(), SendAction::Type::UploadPhoto, 0);
session().data().requestItemRepaint(item);
}
}
void HistoryWidget::documentProgress(const FullMsgId &newId) {
if (const auto item = session().data().message(newId)) {
const auto media = item->media();
const auto document = media ? media->document() : nullptr;
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,
progress);
session().data().requestItemRepaint(item);
}
}
void HistoryWidget::photoFailed(const FullMsgId &newId) {
if (const auto item = session().data().message(newId)) {
updateSendAction(
item->history(),
SendAction::Type::UploadPhoto,
-1);
session().data().requestItemRepaint(item);
}
}
void HistoryWidget::documentFailed(const FullMsgId &newId) {
if (const auto item = session().data().message(newId)) {
const auto media = item->media();
const auto document = media ? media->document() : nullptr;
const auto sendAction = (document && document->isVoiceMessage())
? SendAction::Type::UploadVoice
: SendAction::Type::UploadFile;
updateSendAction(item->history(), sendAction, -1);
session().data().requestItemRepaint(item);
}
}
void HistoryWidget::handleHistoryChange(not_null<const History*> history) {
if (_list && (_history == history || _migrated == history)) {
handlePendingHistoryUpdate();

View File

@ -423,15 +423,6 @@ private:
void stopMessageHighlight();
auto computeSendButtonType() const;
void updateSendAction(
not_null<History*> history,
SendAction::Type type,
int32 progress = 0);
void cancelSendAction(
not_null<History*> history,
SendAction::Type type);
void cancelTypingAction();
void sendActionDone(const MTPBool &result, mtpRequestId requestId);
void animationCallback();
void updateOverStates(QPoint pos);
@ -474,28 +465,6 @@ private:
Api::SendOptions options,
std::shared_ptr<SendingAlbum> album = nullptr);
void subscribeToUploader();
void photoProgress(const FullMsgId &msgId);
void photoFailed(const FullMsgId &msgId);
void documentUploaded(
const FullMsgId &msgId,
Api::SendOptions options,
const MTPInputFile &file);
void thumbDocumentUploaded(
const FullMsgId &msgId,
Api::SendOptions options,
const MTPInputFile &file,
const MTPInputFile &thumb,
bool edit = false);
void documentProgress(const FullMsgId &msgId);
void documentFailed(const FullMsgId &msgId);
void documentEdited(
const FullMsgId &msgId,
Api::SendOptions options,
const MTPInputFile &file);
void itemRemoved(not_null<const HistoryItem*> item);
// Updates position of controls around the message field,
@ -800,11 +769,6 @@ private:
base::Timer _highlightTimer;
crl::time _highlightStart = 0;
base::flat_map<
std::pair<not_null<History*>, SendAction::Type>,
mtpRequestId> _sendActionRequests;
base::Timer _sendActionStopTimer;
crl::time _saveDraftStart = 0;
bool _saveDraftText = false;
QTimer _saveDraftTimer, _saveCloudDraftTimer;

View File

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h"
#include "api/api_updates.h"
#include "api/api_send_progress.h"
#include "core/application.h"
#include "main/main_account.h"
#include "main/main_domain.h"
@ -72,6 +73,7 @@ Session::Session(
, _settings(std::move(settings))
, _api(std::make_unique<ApiWrap>(this))
, _updates(std::make_unique<Api::Updates>(this))
, _sendProgressManager(std::make_unique<Api::SendProgressManager>(this))
, _downloader(std::make_unique<Storage::DownloadManagerMtproto>(_api.get()))
, _uploader(std::make_unique<Storage::Uploader>(_api.get()))
, _storage(std::make_unique<Storage::Facade>())

View File

@ -16,6 +16,7 @@ class ApiWrap;
namespace Api {
class Updates;
class SendProgressManager;
} // namespace Api
namespace MTP {
@ -87,6 +88,9 @@ public:
[[nodiscard]] Api::Updates &updates() const {
return *_updates;
}
[[nodiscard]] Api::SendProgressManager &sendProgressManager() const {
return *_sendProgressManager;
}
[[nodiscard]] Storage::DownloadManagerMtproto &downloader() const {
return *_downloader;
}
@ -162,6 +166,7 @@ private:
const std::unique_ptr<SessionSettings> _settings;
const std::unique_ptr<ApiWrap> _api;
const std::unique_ptr<Api::Updates> _updates;
const std::unique_ptr<Api::SendProgressManager> _sendProgressManager;
const std::unique_ptr<Storage::DownloadManagerMtproto> _downloader;
const std::unique_ptr<Storage::Uploader> _uploader;
const std::unique_ptr<Storage::Facade> _storage;

View File

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "storage/file_upload.h"
#include "api/api_send_progress.h"
#include "storage/localimageloader.h"
#include "storage/file_download.h"
#include "data/data_document.h"
@ -14,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_photo.h"
#include "data/data_session.h"
#include "ui/image/image_location_factory.h"
#include "history/history_item.h"
#include "core/mime_type.h"
#include "main/main_session.h"
#include "apiwrap.h"
@ -153,6 +155,141 @@ Uploader::Uploader(not_null<ApiWrap*> api)
connect(&nextTimer, SIGNAL(timeout()), this, SLOT(sendNext()));
stopSessionsTimer.setSingleShot(true);
connect(&stopSessionsTimer, SIGNAL(timeout()), this, SLOT(stopSessions()));
photoReady(
) | rpl::start_with_next([=](const UploadedPhoto &data) {
if (data.edit) {
_api->editUploadedFile(
data.fullId,
data.file,
std::nullopt,
data.options,
false);
} else {
_api->sendUploadedPhoto(
data.fullId,
data.file,
data.options);
}
}, _lifetime);
documentReady(
) | rpl::start_with_next([=](const UploadedDocument &data) {
if (data.edit) {
_api->editUploadedFile(
data.fullId,
data.file,
std::nullopt,
data.options,
true);
} else {
_api->sendUploadedDocument(
data.fullId,
data.file,
std::nullopt,
data.options);
}
}, _lifetime);
thumbDocumentReady(
) | rpl::start_with_next([=](const UploadedThumbDocument &data) {
if (data.edit) {
_api->editUploadedFile(
data.fullId,
data.file,
data.thumb,
data.options,
true);
} else {
_api->sendUploadedDocument(
data.fullId,
data.file,
data.thumb,
data.options);
}
}, _lifetime);
photoProgress(
) | rpl::start_with_next([=](const FullMsgId &fullId) {
processPhotoProgress(fullId);
}, _lifetime);
photoFailed(
) | rpl::start_with_next([=](const FullMsgId &fullId) {
processPhotoFailed(fullId);
}, _lifetime);
documentProgress(
) | rpl::start_with_next([=](const FullMsgId &fullId) {
processDocumentProgress(fullId);
}, _lifetime);
documentFailed(
) | rpl::start_with_next([=](const FullMsgId &fullId) {
processDocumentFailed(fullId);
}, _lifetime);
}
void Uploader::processPhotoProgress(const FullMsgId &newId) {
const auto session = &_api->session();
if (const auto item = session->data().message(newId)) {
const auto photo = item->media()
? item->media()->photo()
: nullptr;
session->sendProgressManager().update(
item->history(),
Api::SendProgressType::UploadPhoto,
0);
session->data().requestItemRepaint(item);
}
}
void Uploader::processDocumentProgress(const FullMsgId &newId) {
const auto session = &_api->session();
if (const auto item = session->data().message(newId)) {
const auto media = item->media();
const auto document = media ? media->document() : nullptr;
const auto sendAction = (document && document->isVoiceMessage())
? Api::SendProgressType::UploadVoice
: Api::SendProgressType::UploadFile;
const auto progress = (document && document->uploading())
? document->uploadingData->offset
: 0;
session->sendProgressManager().update(
item->history(),
sendAction,
progress);
session->data().requestItemRepaint(item);
}
}
void Uploader::processPhotoFailed(const FullMsgId &newId) {
const auto session = &_api->session();
if (const auto item = session->data().message(newId)) {
session->sendProgressManager().update(
item->history(),
Api::SendProgressType::UploadPhoto,
-1);
session->data().requestItemRepaint(item);
}
}
void Uploader::processDocumentFailed(const FullMsgId &newId) {
const auto session = &_api->session();
if (const auto item = session->data().message(newId)) {
const auto media = item->media();
const auto document = media ? media->document() : nullptr;
const auto sendAction = (document && document->isVoiceMessage())
? Api::SendProgressType::UploadVoice
: Api::SendProgressType::UploadFile;
session->sendProgressManager().update(
item->history(),
sendAction,
-1);
session->data().requestItemRepaint(item);
}
}
Uploader::~Uploader() {
@ -282,7 +419,9 @@ void Uploader::stopSessions() {
}
void Uploader::sendNext() {
if (sentSize >= kMaxUploadFileParallelSize || _pausedId.msg) return;
if (sentSize >= kMaxUploadFileParallelSize || _pausedId.msg) {
return;
}
bool stopping = stopSessionsTimer.isActive();
if (queue.empty()) {

View File

@ -121,6 +121,11 @@ private:
void partLoaded(const MTPBool &result, mtpRequestId requestId);
void partFailed(const RPCError &error, mtpRequestId requestId);
void processPhotoProgress(const FullMsgId &msgId);
void processPhotoFailed(const FullMsgId &msgId);
void processDocumentProgress(const FullMsgId &msgId);
void processDocumentFailed(const FullMsgId &msgId);
void currentFailed();
not_null<ApiWrap*> _api;
@ -147,6 +152,8 @@ private:
rpl::event_stream<FullMsgId> _documentFailed;
rpl::event_stream<FullMsgId> _secureFailed;
rpl::lifetime _lifetime;
};
} // namespace Storage

View File

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "ui/effects/send_action_animations.h"
#include "api/api_send_progress.h"
#include "ui/effects/animation_value.h"
#include "styles/style_widgets.h"
@ -17,7 +18,7 @@ constexpr int kTypingDotsCount = 3;
constexpr int kRecordArcsCount = 4;
constexpr int kUploadArrowsCount = 3;
using ImplementationsMap = QMap<SendAction::Type, const SendActionAnimation::Impl::MetaData*>;
using ImplementationsMap = QMap<Api::SendProgressType, const SendActionAnimation::Impl::MetaData*>;
NeverFreedPointer<ImplementationsMap> Implementations;
class TypingAnimation : public SendActionAnimation::Impl {
@ -162,7 +163,7 @@ void CreateImplementationsMap() {
if (Implementations) {
return;
}
using Type = SendAction::Type;
using Type = Api::SendProgressType;
Implementations.createIfNull();
Type recordTypes[] = {
Type::RecordVideo,

View File

@ -7,11 +7,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
namespace Api {
enum class SendProgressType;
} // namespace Api
namespace Ui {
class SendActionAnimation {
public:
using Type = SendAction::Type;
using Type = Api::SendProgressType;
void start(Type type);
void stop();
@ -31,7 +35,7 @@ public:
class Impl {
public:
using Type = SendAction::Type;
using Type = Api::SendProgressType;
Impl(int period) : _period(period), _started(crl::now()) {
}