Fix finalizing media in non-active account.
This commit is contained in:
parent
000a7ae28b
commit
2f5cb33bf2
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -15,6 +15,7 @@ struct FileLoadResult;
|
|||
namespace Api {
|
||||
|
||||
struct MessageToSend;
|
||||
struct SendAction;
|
||||
|
||||
void SendExistingDocument(
|
||||
Api::MessageToSend &&message,
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>())
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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()) {
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue