mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 02:01:40 -05:00
beta 9026001 message/post edit done
This commit is contained in:
parent
9c8ae7f32b
commit
4ec579112c
18 changed files with 660 additions and 259 deletions
|
@ -127,6 +127,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
"lng_edit_deleted" = "This message was deleted";
|
||||
"lng_edit_too_long" = "Your message text is too long";
|
||||
"lng_edit_message" = "Edit message";
|
||||
"lng_edit_message_text" = "New message text..";
|
||||
"lng_deleted" = "Unknown";
|
||||
"lng_deleted_message" = "Deleted message";
|
||||
|
||||
|
@ -653,6 +654,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
"lng_comment_ph" = "Write a comment..";
|
||||
"lng_broadcast_ph" = "Broadcast a message..";
|
||||
"lng_record_cancel" = "Release outside this field to cancel";
|
||||
"lng_will_be_notified" = "Members will be notified when you post";
|
||||
"lng_wont_be_notified" = "Members will not be notified when you post";
|
||||
"lng_empty_history" = "";
|
||||
"lng_willbe_history" = "Please select a chat to start messaging";
|
||||
"lng_message_with_from" = "[c]{from}:[/c] {message}";
|
||||
|
@ -712,6 +715,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
|
||||
"lng_context_open_link" = "Open Link";
|
||||
"lng_context_copy_link" = "Copy Link";
|
||||
"lng_context_copy_post_link" = "Copy Post Link";
|
||||
"lng_context_open_email" = "Write to this address";
|
||||
"lng_context_copy_email" = "Copy email address";
|
||||
"lng_context_open_hashtag" = "Search by hashtag";
|
||||
|
|
|
@ -1429,6 +1429,7 @@ replyTop: 8px;
|
|||
replyBottom: 6px;
|
||||
replyIconPos: point(13px, 13px);
|
||||
replyIcon: sprite(343px, 197px, 24px, 24px);
|
||||
editIcon: sprite(371px, 286px, 24px, 24px);
|
||||
replyCancel: iconedButton(btnDefIconed) {
|
||||
icon: sprite(165px, 24px, 14px, 14px);
|
||||
iconPos: point(17px, 17px);
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 177 KiB After Width: | Height: | Size: 177 KiB |
Binary file not shown.
Before Width: | Height: | Size: 238 KiB After Width: | Height: | Size: 239 KiB |
|
@ -23,7 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
static const int32 AppVersion = 9026;
|
||||
static const wchar_t *AppVersionStr = L"0.9.26";
|
||||
static const bool DevVersion = false;
|
||||
//#define BETA_VERSION (9019002ULL) // just comment this line to build public version
|
||||
#define BETA_VERSION (9026001ULL) // just comment this line to build public version
|
||||
|
||||
static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)";
|
||||
static const wchar_t *AppName = L"Telegram Desktop";
|
||||
|
|
|
@ -280,7 +280,8 @@ History::History(const PeerId &peerId) : width(0), height(0)
|
|||
, oldLoaded(false)
|
||||
, newLoaded(true)
|
||||
, lastMsg(0)
|
||||
, draftToId(0)
|
||||
, msgDraft(0)
|
||||
, editDraft(0)
|
||||
, lastWidth(0)
|
||||
, lastScrollTop(ScrollMax)
|
||||
, lastShowAtMsgId(ShowAtUnreadMsgId)
|
||||
|
@ -294,8 +295,7 @@ History::History(const PeerId &peerId) : width(0), height(0)
|
|||
, textCachedFor(0)
|
||||
, lastItemTextCache(st::dlgRichMinWidth)
|
||||
, posInDialogs(0)
|
||||
, typingText(st::dlgRichMinWidth)
|
||||
{
|
||||
, typingText(st::dlgRichMinWidth) {
|
||||
if (peer->isChannel() || (peer->isUser() && peer->asUser()->botInfo)) {
|
||||
outboxReadBefore = INT_MAX;
|
||||
}
|
||||
|
@ -2674,6 +2674,12 @@ void History::removeBlock(HistoryBlock *block) {
|
|||
delete block;
|
||||
}
|
||||
|
||||
History::~History() {
|
||||
clear();
|
||||
deleteAndMark(msgDraft);
|
||||
deleteAndMark(editDraft);
|
||||
}
|
||||
|
||||
int32 HistoryBlock::geomResize(int32 newWidth, int32 *ytransform, const HistoryItem *resizedItem) {
|
||||
int32 y = 0;
|
||||
for (Items::iterator i = items.begin(), e = items.end(); i != e; ++i) {
|
||||
|
@ -2926,7 +2932,8 @@ bool HistoryItem::canEdit(const QDateTime &cur) const {
|
|||
t != MediaTypeFile &&
|
||||
t != MediaTypeGif &&
|
||||
t != MediaTypeMusicFile &&
|
||||
t != MediaTypeVoiceFile) {
|
||||
t != MediaTypeVoiceFile &&
|
||||
t != MediaTypeWebPage) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -149,6 +149,42 @@ struct SendAction {
|
|||
int32 progress;
|
||||
};
|
||||
|
||||
struct HistoryDraft {
|
||||
HistoryDraft() : msgId(0), previewCancelled(false) {
|
||||
}
|
||||
HistoryDraft(const QString &text, MsgId msgId, const MessageCursor &cursor, bool previewCancelled)
|
||||
: text(text)
|
||||
, msgId(msgId)
|
||||
, cursor(cursor)
|
||||
, previewCancelled(previewCancelled) {
|
||||
}
|
||||
HistoryDraft(const FlatTextarea &field, MsgId msgId, bool previewCancelled)
|
||||
: text(field.getLastText())
|
||||
, msgId(msgId)
|
||||
, cursor(field)
|
||||
, previewCancelled(previewCancelled) {
|
||||
}
|
||||
QString text;
|
||||
MsgId msgId; // replyToId for message draft, editMsgId for edit draft
|
||||
MessageCursor cursor;
|
||||
bool previewCancelled;
|
||||
};
|
||||
struct HistoryEditDraft : public HistoryDraft {
|
||||
HistoryEditDraft()
|
||||
: HistoryDraft()
|
||||
, saveRequest(0) {
|
||||
}
|
||||
HistoryEditDraft(const QString &text, MsgId msgId, const MessageCursor &cursor, bool previewCancelled, mtpRequestId saveRequest = 0)
|
||||
: HistoryDraft(text, msgId, cursor, previewCancelled)
|
||||
, saveRequest(saveRequest) {
|
||||
}
|
||||
HistoryEditDraft(const FlatTextarea &field, MsgId msgId, bool previewCancelled, mtpRequestId saveRequest = 0)
|
||||
: HistoryDraft(field, msgId, previewCancelled)
|
||||
, saveRequest(saveRequest) {
|
||||
}
|
||||
mtpRequestId saveRequest;
|
||||
};
|
||||
|
||||
class HistoryMedia;
|
||||
class HistoryMessage;
|
||||
class HistoryUnreadBar;
|
||||
|
@ -184,9 +220,7 @@ public:
|
|||
void blockResized(HistoryBlock *block, int32 dh);
|
||||
void removeBlock(HistoryBlock *block);
|
||||
|
||||
virtual ~History() {
|
||||
clear();
|
||||
}
|
||||
virtual ~History();
|
||||
|
||||
HistoryItem *createItem(HistoryBlock *block, const MTPMessage &msg, bool applyServiceAction);
|
||||
HistoryItem *createItemForwarded(HistoryBlock *block, MsgId id, int32 flags, QDateTime date, int32 from, HistoryMessage *msg);
|
||||
|
@ -284,10 +318,20 @@ public:
|
|||
typedef QList<HistoryItem*> NotifyQueue;
|
||||
NotifyQueue notifies;
|
||||
|
||||
QString draft;
|
||||
MsgId draftToId;
|
||||
MessageCursor draftCursor;
|
||||
bool draftPreviewCancelled;
|
||||
HistoryDraft *msgDraft;
|
||||
HistoryEditDraft *editDraft;
|
||||
HistoryDraft *draft() {
|
||||
return editDraft ? editDraft : msgDraft;
|
||||
}
|
||||
void setMsgDraft(HistoryDraft *draft) {
|
||||
if (msgDraft) delete msgDraft;
|
||||
msgDraft = draft;
|
||||
}
|
||||
void setEditDraft(HistoryEditDraft *draft) {
|
||||
if (editDraft) delete editDraft;
|
||||
editDraft = draft;
|
||||
}
|
||||
|
||||
int32 lastWidth, lastScrollTop;
|
||||
MsgId lastShowAtMsgId;
|
||||
bool mute;
|
||||
|
|
|
@ -2609,9 +2609,11 @@ void CollapseButton::paintEvent(QPaintEvent *e) {
|
|||
|
||||
HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
|
||||
, _replyToId(0)
|
||||
, _replyTo(0)
|
||||
, _replyToNameVersion(0)
|
||||
, _replyForwardPreviewCancel(this, st::replyCancel)
|
||||
, _editMsgId(0)
|
||||
, _replyEditMsg(0)
|
||||
, _fieldBarCancel(this, st::replyCancel)
|
||||
, _saveEditMsgRequestId(0)
|
||||
, _reportSpamStatus(dbiprsUnknown)
|
||||
, _previewData(0)
|
||||
, _previewRequest(0)
|
||||
|
@ -2661,7 +2663,10 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
|
|||
, _field(this, st::taMsgField, lang(lng_message_ph))
|
||||
, _a_record(animation(this, &HistoryWidget::step_record))
|
||||
, _a_recording(animation(this, &HistoryWidget::step_recording))
|
||||
, _recording(false), _inRecord(false), _inField(false), _inReply(false)
|
||||
, _recording(false)
|
||||
, _inRecord(false)
|
||||
, _inField(false)
|
||||
, _inReplyEdit(false)
|
||||
, a_recordingLevel(0, 0), _recordingSamples(0)
|
||||
, a_recordOver(0, 0), a_recordDown(0, 0), a_recordCancel(st::recordCancel->c, st::recordCancel->c)
|
||||
, _recordCancelWidth(st::recordFont->width(lang(lng_record_cancel)))
|
||||
|
@ -2697,7 +2702,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
|
|||
connect(&_reportSpamPanel, SIGNAL(clearClicked()), this, SLOT(onReportSpamClear()));
|
||||
connect(&_toHistoryEnd, SIGNAL(clicked()), this, SLOT(onHistoryToEnd()));
|
||||
connect(&_collapseComments, SIGNAL(clicked()), this, SLOT(onCollapseComments()));
|
||||
connect(&_replyForwardPreviewCancel, SIGNAL(clicked()), this, SLOT(onReplyForwardPreviewCancel()));
|
||||
connect(&_fieldBarCancel, SIGNAL(clicked()), this, SLOT(onFieldBarCancel()));
|
||||
connect(&_send, SIGNAL(clicked()), this, SLOT(onSend()));
|
||||
connect(&_unblock, SIGNAL(clicked()), this, SLOT(onUnblock()));
|
||||
connect(&_botStart, SIGNAL(clicked()), this, SLOT(onBotStart()));
|
||||
|
@ -2745,7 +2750,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
|
|||
connect(&_field, SIGNAL(cursorPositionChanged()), this, SLOT(onDraftSaveDelayed()));
|
||||
connect(&_field, SIGNAL(cursorPositionChanged()), this, SLOT(onCheckMentionDropdown()), Qt::QueuedConnection);
|
||||
|
||||
_replyForwardPreviewCancel.hide();
|
||||
_fieldBarCancel.hide();
|
||||
|
||||
_scroll.hide();
|
||||
_scroll.move(0, 0);
|
||||
|
@ -2897,20 +2902,20 @@ void HistoryWidget::onTextChange() {
|
|||
updateStickersByEmoji();
|
||||
|
||||
if (_peer && (!_peer->isChannel() || _peer->isMegagroup() || !_peer->asChannel()->canPublish() || (!_peer->asChannel()->isBroadcast() && !_broadcast.checked()))) {
|
||||
if (!_inlineBot && (_textUpdateEventsFlags & TextUpdateEventsSendTyping)) {
|
||||
if (!_inlineBot && !_editMsgId && (_textUpdateEventsFlags & TextUpdateEventsSendTyping)) {
|
||||
updateSendAction(_history, SendActionTyping);
|
||||
}
|
||||
}
|
||||
|
||||
if (cHasAudioCapture()) {
|
||||
if (!_field.hasSendText() && !readyToForward()) {
|
||||
if (!_field.hasSendText() && !readyToForward() && !_editMsgId) {
|
||||
_previewCancelled = false;
|
||||
_send.hide();
|
||||
setMouseTracking(true);
|
||||
updateMouseTracking();
|
||||
mouseMoveEvent(0);
|
||||
} else if (!_field.isHidden() && _send.isHidden()) {
|
||||
_send.show();
|
||||
setMouseTracking(false);
|
||||
updateMouseTracking();
|
||||
_a_record.stop();
|
||||
_inRecord = _inField = false;
|
||||
a_recordOver = a_recordDown = anim::fvalue(0, 0);
|
||||
|
@ -2931,7 +2936,9 @@ void HistoryWidget::onTextChange() {
|
|||
void HistoryWidget::onDraftSaveDelayed() {
|
||||
if (!_peer || !(_textUpdateEventsFlags & TextUpdateEventsSaveDraft)) return;
|
||||
if (!_field.textCursor().anchor() && !_field.textCursor().position() && !_field.verticalScrollBar()->value()) {
|
||||
if (!Local::hasDraftPositions(_peer->id)) return;
|
||||
if (!Local::hasDraftCursors(_peer->id)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
onDraftSave(true);
|
||||
}
|
||||
|
@ -2947,30 +2954,77 @@ void HistoryWidget::onDraftSave(bool delayed) {
|
|||
return _saveDraftTimer.start(SaveDraftTimeout);
|
||||
}
|
||||
}
|
||||
writeDraft();
|
||||
writeDrafts(Nil, Nil);
|
||||
}
|
||||
|
||||
void HistoryWidget::writeDraft(MsgId *replyTo, const QString *text, const MessageCursor *cursor, bool *previewCancelled) {
|
||||
void HistoryWidget::writeDrafts(HistoryDraft **msgDraft, HistoryEditDraft **editDraft) {
|
||||
if (!msgDraft && _editMsgId) msgDraft = &_history->msgDraft;
|
||||
|
||||
bool save = _peer && (_saveDraftStart > 0);
|
||||
_saveDraftStart = 0;
|
||||
_saveDraftTimer.stop();
|
||||
if (_saveDraftText) {
|
||||
if (save) {
|
||||
Local::writeDraft(_peer->id, Local::MessageDraft(replyTo ? (*replyTo) : _replyToId, text ? (*text) : _field.getLastText(), previewCancelled ? (*previewCancelled) : _previewCancelled));
|
||||
Local::MessageDraft localMsgDraft, localEditDraft;
|
||||
if (msgDraft) {
|
||||
if (*msgDraft) {
|
||||
localMsgDraft = Local::MessageDraft((*msgDraft)->msgId, (*msgDraft)->text, (*msgDraft)->previewCancelled);
|
||||
}
|
||||
} else {
|
||||
localMsgDraft = Local::MessageDraft(_replyToId, _field.getLastText(), _previewCancelled);
|
||||
}
|
||||
if (editDraft) {
|
||||
if (*editDraft) {
|
||||
localEditDraft = Local::MessageDraft((*editDraft)->msgId, (*editDraft)->text, (*editDraft)->previewCancelled);
|
||||
}
|
||||
} else if (_editMsgId) {
|
||||
localEditDraft = Local::MessageDraft(_editMsgId, _field.getLastText(), _previewCancelled);
|
||||
}
|
||||
Local::writeDrafts(_peer->id, localMsgDraft, localEditDraft);
|
||||
if (_migrated) {
|
||||
Local::writeDraft(_migrated->peer->id, Local::MessageDraft());
|
||||
Local::writeDrafts(_migrated->peer->id, Local::MessageDraft(), Local::MessageDraft());
|
||||
}
|
||||
}
|
||||
_saveDraftText = false;
|
||||
}
|
||||
if (save) {
|
||||
Local::writeDraftPositions(_peer->id, cursor ? (*cursor) : MessageCursor(_field));
|
||||
MessageCursor msgCursor, editCursor;
|
||||
if (msgDraft) {
|
||||
if (*msgDraft) {
|
||||
msgCursor = (*msgDraft)->cursor;
|
||||
}
|
||||
} else {
|
||||
msgCursor = MessageCursor(_field);
|
||||
}
|
||||
if (editDraft) {
|
||||
if (*editDraft) {
|
||||
editCursor = (*editDraft)->cursor;
|
||||
}
|
||||
} else if (_editMsgId) {
|
||||
editCursor = MessageCursor(_field);
|
||||
}
|
||||
Local::writeDraftCursors(_peer->id, msgCursor, editCursor);
|
||||
if (_migrated) {
|
||||
Local::writeDraftPositions(_migrated->peer->id, MessageCursor());
|
||||
Local::writeDraftCursors(_migrated->peer->id, MessageCursor(), MessageCursor());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::writeDrafts(History *history) {
|
||||
Local::MessageDraft localMsgDraft, localEditDraft;
|
||||
MessageCursor msgCursor, editCursor;
|
||||
if (history->msgDraft) {
|
||||
localMsgDraft = Local::MessageDraft(history->msgDraft->msgId, history->msgDraft->text, history->msgDraft->previewCancelled);
|
||||
msgCursor = history->msgDraft->cursor;
|
||||
}
|
||||
if (history->editDraft) {
|
||||
localEditDraft = Local::MessageDraft(history->editDraft->msgId, history->editDraft->text, history->editDraft->previewCancelled);
|
||||
editCursor = history->editDraft->cursor;
|
||||
}
|
||||
Local::writeDrafts(history->peer->id, localMsgDraft, localEditDraft);
|
||||
Local::writeDraftCursors(history->peer->id, msgCursor, editCursor);
|
||||
}
|
||||
|
||||
void HistoryWidget::cancelSendAction(History *history, SendActionType type) {
|
||||
QMap<QPair<History*, SendActionType>, mtpRequestId>::iterator i = _sendActionRequests.find(qMakePair(history, type));
|
||||
if (i != _sendActionRequests.cend()) {
|
||||
|
@ -3374,16 +3428,36 @@ void HistoryWidget::fastShowAtEnd(History *h) {
|
|||
}
|
||||
|
||||
void HistoryWidget::applyDraft(bool parseLinks) {
|
||||
if (!_history) return;
|
||||
setFieldText(_history->draft);
|
||||
_field.setFocus();
|
||||
HistoryDraft *draft = _history ? _history->draft() : 0;
|
||||
if (!draft) {
|
||||
setFieldText(QString());
|
||||
_field.setFocus();
|
||||
_editMsgId = _replyToId = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
_textUpdateEventsFlags = 0;
|
||||
_history->draftCursor.applyTo(_field);
|
||||
setFieldText(draft->text);
|
||||
_field.setFocus();
|
||||
draft->cursor.applyTo(_field);
|
||||
_textUpdateEventsFlags = TextUpdateEventsSaveDraft | TextUpdateEventsSendTyping;
|
||||
_previewCancelled = _history->draftPreviewCancelled;
|
||||
_previewCancelled = draft->previewCancelled;
|
||||
if (_history->editDraft) {
|
||||
_editMsgId = _history->editDraft->msgId;
|
||||
_replyToId = 0;
|
||||
} else {
|
||||
_editMsgId = 0;
|
||||
_replyToId = readyToForward() ? 0 : _history->msgDraft->msgId;
|
||||
}
|
||||
if (parseLinks) {
|
||||
onPreviewParse();
|
||||
}
|
||||
if (_editMsgId || _replyToId) {
|
||||
updateReplyEditTexts();
|
||||
if (!_replyEditMsg && App::api()) {
|
||||
App::api()->requestReplyTo(0, _peer->asChannel(), _editMsgId ? _editMsgId : _replyToId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool reload) {
|
||||
|
@ -3441,13 +3515,22 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re
|
|||
clearAllLoadRequests();
|
||||
|
||||
if (_history) {
|
||||
_history->draft = _field.getLastText();
|
||||
if (_migrated) _migrated->draft = QString(); // use migrated draft only once
|
||||
_history->draftCursor.fillFrom(_field);
|
||||
_history->draftToId = _replyToId;
|
||||
_history->draftPreviewCancelled = _previewCancelled;
|
||||
if (_editMsgId) {
|
||||
_history->setEditDraft(new HistoryEditDraft(_field, _editMsgId, _previewCancelled, _saveEditMsgRequestId));
|
||||
} else {
|
||||
if (_replyToId || !_field.getLastText().isEmpty()) {
|
||||
_history->setMsgDraft(new HistoryDraft(_field, _replyToId, _previewCancelled));
|
||||
} else {
|
||||
_history->setMsgDraft(Nil);
|
||||
}
|
||||
_history->setEditDraft(Nil);
|
||||
}
|
||||
if (_migrated) {
|
||||
_migrated->setMsgDraft(Nil); // use migrated draft only once
|
||||
_migrated->setEditDraft(Nil);
|
||||
}
|
||||
|
||||
writeDraft(&_history->draftToId, &_history->draft, &_history->draftCursor, &_history->draftPreviewCancelled);
|
||||
writeDrafts(&_history->msgDraft, &_history->editDraft);
|
||||
|
||||
if (_scroll.scrollTop() + 1 <= _scroll.scrollTopMax()) {
|
||||
_history->lastWidth = _list->width();
|
||||
|
@ -3467,16 +3550,14 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re
|
|||
updateBotKeyboard();
|
||||
}
|
||||
|
||||
if (_replyToId) {
|
||||
_replyTo = 0;
|
||||
_replyToId = 0;
|
||||
_replyForwardPreviewCancel.hide();
|
||||
}
|
||||
if (_previewData && _previewData->pendingTill >= 0) {
|
||||
_previewData = 0;
|
||||
_replyForwardPreviewCancel.hide();
|
||||
}
|
||||
_editMsgId = 0;
|
||||
_saveEditMsgRequestId = 0;
|
||||
_replyToId = 0;
|
||||
_replyEditMsg = 0;
|
||||
_previewData = 0;
|
||||
_previewCache.clear();
|
||||
_fieldBarCancel.hide();
|
||||
|
||||
if (_list) _list->deleteLater();
|
||||
_list = 0;
|
||||
_scroll.takeWidget();
|
||||
|
@ -3552,39 +3633,20 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re
|
|||
|
||||
App::main()->peerUpdated(_peer);
|
||||
|
||||
if (_history->draftToId > 0 || !_history->draft.isEmpty()) {
|
||||
applyDraft(false);
|
||||
_replyToId = readyToForward() ? 0 : _history->draftToId;
|
||||
} else if (_migrated && !_migrated->draft.isEmpty()) {
|
||||
_history->draft = _migrated->draft;
|
||||
_history->draftCursor = _migrated->draftCursor;
|
||||
_history->draftPreviewCancelled = _migrated->draftPreviewCancelled;
|
||||
_history->draftToId = 0;
|
||||
_migrated->draft = QString(); // use migrated draft only once
|
||||
applyDraft(false);
|
||||
_replyToId = 0;
|
||||
} else {
|
||||
bool fromMigrated = false;
|
||||
Local::MessageDraft draft = Local::readDraft(_peer->id);
|
||||
if (draft.replyTo <= 0 && draft.text.isEmpty() && _migrated) {
|
||||
fromMigrated = true;
|
||||
draft = Local::readDraft(_migrated->peer->id);
|
||||
Local::readDraftsWithCursors(_history);
|
||||
if (_migrated) {
|
||||
Local::readDraftsWithCursors(_migrated);
|
||||
_migrated->setEditDraft(Nil);
|
||||
if (_migrated->msgDraft && !_migrated->msgDraft->text.isEmpty()) {
|
||||
_migrated->msgDraft->msgId = 0; // edit and reply to drafts can't migrate
|
||||
if (!_history->msgDraft) {
|
||||
_history->setMsgDraft(new HistoryDraft(*_migrated->msgDraft));
|
||||
}
|
||||
}
|
||||
setFieldText(draft.text);
|
||||
_field.setFocus();
|
||||
if (!draft.text.isEmpty()) {
|
||||
MessageCursor cur = Local::readDraftPositions(fromMigrated ? _migrated->peer->id : _peer->id);
|
||||
_textUpdateEventsFlags = 0;
|
||||
cur.applyTo(_field);
|
||||
_textUpdateEventsFlags = TextUpdateEventsSaveDraft | TextUpdateEventsSendTyping;
|
||||
}
|
||||
_replyToId = readyToForward() ? 0 : draft.replyTo;
|
||||
_previewCancelled = draft.previewCancelled;
|
||||
}
|
||||
if (_replyToId) {
|
||||
updateReplyTo();
|
||||
if (!_replyTo && App::api()) App::api()->requestReplyTo(0, _peer->asChannel(), _replyToId);
|
||||
_migrated->setMsgDraft(Nil);
|
||||
}
|
||||
applyDraft(false);
|
||||
|
||||
resizeEvent(0);
|
||||
if (!_previewCancelled) {
|
||||
onPreviewParse();
|
||||
|
@ -3755,7 +3817,7 @@ void HistoryWidget::updateControlsVisibility() {
|
|||
_muteUnmute.hide();
|
||||
_attachMention.hide();
|
||||
_field.hide();
|
||||
_replyForwardPreviewCancel.hide();
|
||||
_fieldBarCancel.hide();
|
||||
_attachDocument.hide();
|
||||
_attachPhoto.hide();
|
||||
_attachEmoji.hide();
|
||||
|
@ -3812,7 +3874,7 @@ void HistoryWidget::updateControlsVisibility() {
|
|||
_attachPhoto.hide();
|
||||
_broadcast.hide();
|
||||
_kbScroll.hide();
|
||||
_replyForwardPreviewCancel.hide();
|
||||
_fieldBarCancel.hide();
|
||||
_attachDocument.hide();
|
||||
_attachPhoto.hide();
|
||||
_attachEmoji.hide();
|
||||
|
@ -3849,7 +3911,7 @@ void HistoryWidget::updateControlsVisibility() {
|
|||
_attachPhoto.hide();
|
||||
_broadcast.hide();
|
||||
_kbScroll.hide();
|
||||
_replyForwardPreviewCancel.hide();
|
||||
_fieldBarCancel.hide();
|
||||
} else {
|
||||
_unblock.hide();
|
||||
_botStart.hide();
|
||||
|
@ -3857,11 +3919,9 @@ void HistoryWidget::updateControlsVisibility() {
|
|||
_muteUnmute.hide();
|
||||
if (cHasAudioCapture() && !_field.hasSendText() && !readyToForward()) {
|
||||
_send.hide();
|
||||
setMouseTracking(true);
|
||||
mouseMoveEvent(0);
|
||||
} else {
|
||||
_send.show();
|
||||
setMouseTracking(false);
|
||||
_a_record.stop();
|
||||
_inRecord = _inField = false;
|
||||
a_recordOver = anim::fvalue(0, 0);
|
||||
|
@ -3924,14 +3984,14 @@ void HistoryWidget::updateControlsVisibility() {
|
|||
}
|
||||
updateFieldPlaceholder();
|
||||
}
|
||||
if (_replyToId || readyToForward() || (_previewData && _previewData->pendingTill >= 0) || _kbReplyTo) {
|
||||
if (_replyForwardPreviewCancel.isHidden()) {
|
||||
_replyForwardPreviewCancel.show();
|
||||
if (_editMsgId || _replyToId || readyToForward() || (_previewData && _previewData->pendingTill >= 0) || _kbReplyTo) {
|
||||
if (_fieldBarCancel.isHidden()) {
|
||||
_fieldBarCancel.show();
|
||||
resizeEvent(0);
|
||||
update();
|
||||
}
|
||||
} else {
|
||||
_replyForwardPreviewCancel.hide();
|
||||
_fieldBarCancel.hide();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -3945,7 +4005,7 @@ void HistoryWidget::updateControlsVisibility() {
|
|||
_attachPhoto.hide();
|
||||
_broadcast.hide();
|
||||
_kbScroll.hide();
|
||||
_replyForwardPreviewCancel.hide();
|
||||
_fieldBarCancel.hide();
|
||||
_attachDocument.hide();
|
||||
_attachPhoto.hide();
|
||||
_attachEmoji.hide();
|
||||
|
@ -3961,6 +4021,12 @@ void HistoryWidget::updateControlsVisibility() {
|
|||
update();
|
||||
}
|
||||
}
|
||||
updateMouseTracking();
|
||||
}
|
||||
|
||||
void HistoryWidget::updateMouseTracking() {
|
||||
bool trackMouse = !_fieldBarCancel.isHidden() || (cHasAudioCapture() && _send.isHidden() && !_field.isHidden());
|
||||
setMouseTracking(trackMouse);
|
||||
}
|
||||
|
||||
void HistoryWidget::newUnreadMsg(History *history, HistoryItem *item) {
|
||||
|
@ -4432,12 +4498,84 @@ void HistoryWidget::onCollapseComments() {
|
|||
showHistory(_peer->id, switchAt);
|
||||
}
|
||||
|
||||
void HistoryWidget::saveEditMsg() {
|
||||
if (_saveEditMsgRequestId) return;
|
||||
|
||||
WebPageId webPageId = _previewCancelled ? CancelledWebPageId : ((_previewData && _previewData->pendingTill >= 0) ? _previewData->id : 0);
|
||||
|
||||
EntitiesInText sendingEntities, leftEntities;
|
||||
QString sendingText, leftText = prepareTextWithEntities(_field.getLastText(), leftEntities, itemTextOptions(_history, App::self()).flags);
|
||||
|
||||
if (!textSplit(sendingText, sendingEntities, leftText, leftEntities, MaxMessageSize)) {
|
||||
_field.selectAll();
|
||||
_field.setFocus();
|
||||
return;
|
||||
} else if (!leftText.isEmpty()) {
|
||||
Ui::showLayer(new InformBox(lang(lng_edit_too_long)));
|
||||
return;
|
||||
}
|
||||
|
||||
int32 sendFlags = 0;
|
||||
if (webPageId == CancelledWebPageId) {
|
||||
sendFlags |= MTPmessages_SendMessage::flag_no_webpage;
|
||||
}
|
||||
MTPVector<MTPMessageEntity> localEntities = linksToMTP(sendingEntities), sentEntities = linksToMTP(sendingEntities, true);
|
||||
if (!sentEntities.c_vector().v.isEmpty()) {
|
||||
sendFlags |= MTPmessages_SendMessage::flag_entities;
|
||||
}
|
||||
_saveEditMsgRequestId = MTP::send(MTPchannels_EditMessage(MTP_int(sendFlags), _history->peer->asChannel()->inputChannel, MTP_int(_editMsgId), MTP_string(sendingText), sentEntities), rpcDone(&HistoryWidget::saveEditMsgDone, _history), rpcFail(&HistoryWidget::saveEditMsgFail, _history));
|
||||
}
|
||||
|
||||
void HistoryWidget::saveEditMsgDone(History *history, const MTPUpdates &updates, mtpRequestId req) {
|
||||
if (App::main()) {
|
||||
App::main()->sentUpdatesReceived(updates);
|
||||
}
|
||||
if (req == _saveEditMsgRequestId) {
|
||||
_saveEditMsgRequestId = 0;
|
||||
cancelEdit();
|
||||
}
|
||||
if (history->editDraft && history->editDraft->saveRequest == req) {
|
||||
history->setEditDraft(Nil);
|
||||
writeDrafts(history);
|
||||
}
|
||||
}
|
||||
|
||||
bool HistoryWidget::saveEditMsgFail(History *history, const RPCError &error, mtpRequestId req) {
|
||||
if (mtpIsFlood(error)) return false;
|
||||
if (req == _saveEditMsgRequestId) {
|
||||
_saveEditMsgRequestId = 0;
|
||||
}
|
||||
if (history->editDraft && history->editDraft->saveRequest == req) {
|
||||
history->editDraft->saveRequest = 0;
|
||||
}
|
||||
|
||||
QString err = error.type();
|
||||
if (err == qstr("MESSAGE_ID_INVALID") || err == qstr("CHAT_ADMIN_REQUIRED") || err == qstr("MESSAGE_EDIT_TIME_EXPIRED")) {
|
||||
Ui::showLayer(new InformBox(lang(lng_edit_error)));
|
||||
} else if (err == qstr("MESSAGE_NOT_MODIFIED")) {
|
||||
cancelEdit();
|
||||
} else if (err == qstr("MESSAGE_EMPTY")) {
|
||||
_field.selectAll();
|
||||
_field.setFocus();
|
||||
} else {
|
||||
Ui::showLayer(new InformBox(lang(lng_edit_error)));
|
||||
}
|
||||
update();
|
||||
return true;
|
||||
}
|
||||
|
||||
void HistoryWidget::onSend(bool ctrlShiftEnter, MsgId replyTo) {
|
||||
if (!_history) return;
|
||||
|
||||
if (_editMsgId) {
|
||||
saveEditMsg();
|
||||
return;
|
||||
}
|
||||
|
||||
bool lastKeyboardUsed = lastForceReplyReplied(FullMsgId(_channel, replyTo));
|
||||
|
||||
WebPageId webPageId = _previewCancelled ? CancelledWebPageId : ((_previewData && _previewData->pendingTill >= 0) ? _previewData->id : 0);
|
||||
|
||||
App::main()->sendMessage(_history, _field.getLastText(), replyTo, _broadcast.checked(), webPageId);
|
||||
|
||||
setFieldText(QString());
|
||||
|
@ -4658,7 +4796,7 @@ void HistoryWidget::animShow(const QPixmap &bgAnimCache, const QPixmap &bgAnimTo
|
|||
_kbHide.hide();
|
||||
_cmdStart.hide();
|
||||
_field.hide();
|
||||
_replyForwardPreviewCancel.hide();
|
||||
_fieldBarCancel.hide();
|
||||
_send.hide();
|
||||
_unblock.hide();
|
||||
_botStart.hide();
|
||||
|
@ -4846,7 +4984,7 @@ void HistoryWidget::mouseMoveEvent(QMouseEvent *e) {
|
|||
QPoint pos(e ? e->pos() : mapFromGlobal(QCursor::pos()));
|
||||
bool inRecord = _send.geometry().contains(pos);
|
||||
bool inField = pos.y() >= (_scroll.y() + _scroll.height()) && pos.y() < height() && pos.x() >= 0 && pos.x() < width();
|
||||
bool inReply = QRect(st::replySkip, _field.y() - st::sendPadding - st::replyHeight, width() - st::replySkip - _replyForwardPreviewCancel.width(), st::replyHeight).contains(pos) && replyToId();
|
||||
bool inReplyEdit = QRect(st::replySkip, _field.y() - st::sendPadding - st::replyHeight, width() - st::replySkip - _fieldBarCancel.width(), st::replyHeight).contains(pos) && (_editMsgId || replyToId());
|
||||
bool startAnim = false;
|
||||
if (inRecord != _inRecord) {
|
||||
_inRecord = inRecord;
|
||||
|
@ -4862,9 +5000,9 @@ void HistoryWidget::mouseMoveEvent(QMouseEvent *e) {
|
|||
a_recordCancel.start(_inField ? st::recordCancel->c : st::recordCancelActive->c);
|
||||
startAnim = true;
|
||||
}
|
||||
if (inReply != _inReply) {
|
||||
_inReply = inReply;
|
||||
setCursor(inReply ? style::cur_pointer : style::cur_default);
|
||||
if (inReplyEdit != _inReplyEdit) {
|
||||
_inReplyEdit = inReplyEdit;
|
||||
setCursor(inReplyEdit ? style::cur_pointer : style::cur_default);
|
||||
}
|
||||
if (startAnim) _a_record.start();
|
||||
}
|
||||
|
@ -5204,8 +5342,9 @@ void HistoryWidget::onKbToggle(bool manual) {
|
|||
_field.setMaxHeight(st::maxFieldHeight);
|
||||
|
||||
_kbReplyTo = 0;
|
||||
if (!readyToForward() && (!_previewData || _previewData->pendingTill < 0) && !_replyToId) {
|
||||
_replyForwardPreviewCancel.hide();
|
||||
if (!readyToForward() && (!_previewData || _previewData->pendingTill < 0) && !_editMsgId && !_replyToId) {
|
||||
_fieldBarCancel.hide();
|
||||
updateMouseTracking();
|
||||
}
|
||||
} else {
|
||||
if (_history) {
|
||||
|
@ -5223,10 +5362,11 @@ void HistoryWidget::onKbToggle(bool manual) {
|
|||
_field.setMaxHeight(st::maxFieldHeight);
|
||||
|
||||
_kbReplyTo = (_peer->isChat() || _peer->isChannel() || _keyboard.forceReply()) ? App::histItemById(_keyboard.forMsgId()) : 0;
|
||||
if (_kbReplyTo && !_replyToId) {
|
||||
if (_kbReplyTo && !_editMsgId && !_replyToId) {
|
||||
updateReplyToName();
|
||||
_replyToText.setText(st::msgFont, _kbReplyTo->inDialogsText(), _textDlgOptions);
|
||||
_replyForwardPreviewCancel.show();
|
||||
_replyEditMsgText.setText(st::msgFont, _kbReplyTo->inDialogsText(), _textDlgOptions);
|
||||
_fieldBarCancel.show();
|
||||
updateMouseTracking();
|
||||
}
|
||||
if (manual && _history) {
|
||||
_history->lastKeyboardHiddenId = 0;
|
||||
|
@ -5241,10 +5381,11 @@ void HistoryWidget::onKbToggle(bool manual) {
|
|||
_field.setMaxHeight(st::maxFieldHeight - maxh);
|
||||
|
||||
_kbReplyTo = (_peer->isChat() || _peer->isChannel() || _keyboard.forceReply()) ? App::histItemById(_keyboard.forMsgId()) : 0;
|
||||
if (_kbReplyTo && !_replyToId) {
|
||||
if (_kbReplyTo && !_editMsgId && !_replyToId) {
|
||||
updateReplyToName();
|
||||
_replyToText.setText(st::msgFont, _kbReplyTo->inDialogsText(), _textDlgOptions);
|
||||
_replyForwardPreviewCancel.show();
|
||||
_replyEditMsgText.setText(st::msgFont, _kbReplyTo->inDialogsText(), _textDlgOptions);
|
||||
_fieldBarCancel.show();
|
||||
updateMouseTracking();
|
||||
}
|
||||
if (manual && _history) {
|
||||
_history->lastKeyboardHiddenId = 0;
|
||||
|
@ -5414,7 +5555,7 @@ void HistoryWidget::onFieldResize() {
|
|||
_kbScroll.setGeometry(0, height() - kbh, width(), kbh);
|
||||
}
|
||||
_field.move(_attachDocument.x() + _attachDocument.width(), height() - kbh - _field.height() - st::sendPadding);
|
||||
_replyForwardPreviewCancel.move(width() - _replyForwardPreviewCancel.width(), _field.y() - st::sendPadding - _replyForwardPreviewCancel.height());
|
||||
_fieldBarCancel.move(width() - _fieldBarCancel.width(), _field.y() - st::sendPadding - _fieldBarCancel.height());
|
||||
|
||||
_attachDocument.move(0, height() - kbh - _attachDocument.height());
|
||||
_attachPhoto.move(_attachDocument.x(), _attachDocument.y());
|
||||
|
@ -5454,12 +5595,18 @@ void HistoryWidget::onCheckMentionDropdown() {
|
|||
}
|
||||
|
||||
void HistoryWidget::updateFieldPlaceholder() {
|
||||
if (_inlineBot && _inlineBot != InlineBotLookingUpData) {
|
||||
_field.setPlaceholder(_inlineBot->botInfo->inlinePlaceholder.mid(1), _inlineBot->username.size() + 2);
|
||||
} else if (hasBroadcastToggle()) {
|
||||
_field.setPlaceholder(lang(_broadcast.checked() ? lng_broadcast_ph : lng_comment_ph));
|
||||
if (_editMsgId) {
|
||||
_field.setPlaceholder(lang(lng_edit_message_text));
|
||||
_send.setText(lang(lng_settings_save));
|
||||
} else {
|
||||
_field.setPlaceholder(lang((_history && _history->isChannel() && !_history->isMegagroup()) ? (_peer->asChannel()->canPublish() ? lng_broadcast_ph : lng_comment_ph) : lng_message_ph));
|
||||
if (_inlineBot && _inlineBot != InlineBotLookingUpData) {
|
||||
_field.setPlaceholder(_inlineBot->botInfo->inlinePlaceholder.mid(1), _inlineBot->username.size() + 2);
|
||||
} else if (hasBroadcastToggle()) {
|
||||
_field.setPlaceholder(lang(_broadcast.checked() ? lng_broadcast_ph : lng_comment_ph));
|
||||
} else {
|
||||
_field.setPlaceholder(lang((_history && _history->isChannel() && !_history->isMegagroup()) ? (_peer->asChannel()->canPublish() ? lng_broadcast_ph : lng_comment_ph) : lng_message_ph));
|
||||
}
|
||||
_send.setText(lang(lng_send_button));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5896,7 +6043,7 @@ void HistoryWidget::resizeEvent(QResizeEvent *e) {
|
|||
_attachDocument.move(0, height() - kbh - _attachDocument.height());
|
||||
_attachPhoto.move(_attachDocument.x(), _attachDocument.y());
|
||||
|
||||
_replyForwardPreviewCancel.move(width() - _replyForwardPreviewCancel.width(), _field.y() - st::sendPadding - _replyForwardPreviewCancel.height());
|
||||
_fieldBarCancel.move(width() - _fieldBarCancel.width(), _field.y() - st::sendPadding - _fieldBarCancel.height());
|
||||
updateListSize(App::main() ? App::main()->contentScrollAddToY() : 0);
|
||||
|
||||
bool kbShowShown = _history && !_kbShown && _keyboard.hasMarkup();
|
||||
|
@ -5945,8 +6092,12 @@ void HistoryWidget::resizeEvent(QResizeEvent *e) {
|
|||
|
||||
void HistoryWidget::itemRemoved(HistoryItem *item) {
|
||||
if (_list) _list->itemRemoved(item);
|
||||
if (item == _replyTo) {
|
||||
cancelReply();
|
||||
if (item == _replyEditMsg) {
|
||||
if (_editMsgId) {
|
||||
cancelEdit();
|
||||
} else {
|
||||
cancelReply();
|
||||
}
|
||||
}
|
||||
if (item == _replyReturn) {
|
||||
calcNextReplyReturn();
|
||||
|
@ -5980,7 +6131,7 @@ void HistoryWidget::updateListSize(int32 addToY, bool initial, bool loadedDown,
|
|||
if (_canSendMessages) {
|
||||
newScrollHeight -= (_field.height() + 2 * st::sendPadding);
|
||||
}
|
||||
if (replyToId() || readyToForward() || (_previewData && _previewData->pendingTill >= 0)) {
|
||||
if (_editMsgId || replyToId() || readyToForward() || (_previewData && _previewData->pendingTill >= 0)) {
|
||||
newScrollHeight -= st::replyHeight;
|
||||
}
|
||||
if (_kbShown) {
|
||||
|
@ -6163,22 +6314,22 @@ void HistoryWidget::updateBotKeyboard(History *h) {
|
|||
|
||||
bool changed = false;
|
||||
bool wasVisible = _kbShown || _kbReplyTo;
|
||||
if ((_replyToId && !_replyTo) || !_history) {
|
||||
if ((_replyToId && !_replyEditMsg) || _editMsgId || !_history) {
|
||||
changed = _keyboard.updateMarkup(0);
|
||||
} else if (_replyTo) {
|
||||
changed = _keyboard.updateMarkup(_replyTo);
|
||||
} else if (_replyToId && _replyEditMsg) {
|
||||
changed = _keyboard.updateMarkup(_replyEditMsg);
|
||||
} else {
|
||||
changed = _keyboard.updateMarkup(_history->lastKeyboardId ? App::histItemById(_channel, _history->lastKeyboardId) : 0);
|
||||
}
|
||||
updateCmdStartShown();
|
||||
if (!changed) return;
|
||||
|
||||
bool hasMarkup = _keyboard.hasMarkup(), forceReply = _keyboard.forceReply() && !_replyTo;
|
||||
bool hasMarkup = _keyboard.hasMarkup(), forceReply = _keyboard.forceReply() && (!_replyToId || !_replyEditMsg);
|
||||
if (hasMarkup || forceReply) {
|
||||
if (_keyboard.singleUse() && _keyboard.hasMarkup() && _keyboard.forMsgId() == FullMsgId(_channel, _history->lastKeyboardId) && _history->lastKeyboardUsed) {
|
||||
_history->lastKeyboardHiddenId = _history->lastKeyboardId;
|
||||
}
|
||||
if (!isBotStart() && !isBlocked() && _canSendMessages && (wasVisible || _replyTo || (!_field.hasSendText() && !kbWasHidden()))) {
|
||||
if (!isBotStart() && !isBlocked() && _canSendMessages && (wasVisible || (_replyToId && _replyEditMsg) || (!_field.hasSendText() && !kbWasHidden()))) {
|
||||
if (!_a_show.animating()) {
|
||||
if (hasMarkup) {
|
||||
_kbScroll.show();
|
||||
|
@ -6198,8 +6349,9 @@ void HistoryWidget::updateBotKeyboard(History *h) {
|
|||
_kbReplyTo = (_peer->isChat() || _peer->isChannel() || _keyboard.forceReply()) ? App::histItemById(_keyboard.forMsgId()) : 0;
|
||||
if (_kbReplyTo && !_replyToId) {
|
||||
updateReplyToName();
|
||||
_replyToText.setText(st::msgFont, _kbReplyTo->inDialogsText(), _textDlgOptions);
|
||||
_replyForwardPreviewCancel.show();
|
||||
_replyEditMsgText.setText(st::msgFont, _kbReplyTo->inDialogsText(), _textDlgOptions);
|
||||
_fieldBarCancel.show();
|
||||
updateMouseTracking();
|
||||
}
|
||||
} else {
|
||||
if (!_a_show.animating()) {
|
||||
|
@ -6213,7 +6365,8 @@ void HistoryWidget::updateBotKeyboard(History *h) {
|
|||
_kbShown = false;
|
||||
_kbReplyTo = 0;
|
||||
if (!readyToForward() && (!_previewData || _previewData->pendingTill < 0) && !_replyToId) {
|
||||
_replyForwardPreviewCancel.hide();
|
||||
_fieldBarCancel.hide();
|
||||
updateMouseTracking();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -6227,8 +6380,9 @@ void HistoryWidget::updateBotKeyboard(History *h) {
|
|||
_field.setMaxHeight(st::maxFieldHeight);
|
||||
_kbShown = false;
|
||||
_kbReplyTo = 0;
|
||||
if (!readyToForward() && (!_previewData || _previewData->pendingTill < 0) && !_replyToId) {
|
||||
_replyForwardPreviewCancel.hide();
|
||||
if (!readyToForward() && (!_previewData || _previewData->pendingTill < 0) && !_replyToId && !_editMsgId) {
|
||||
_fieldBarCancel.hide();
|
||||
updateMouseTracking();
|
||||
}
|
||||
}
|
||||
resizeEvent(0);
|
||||
|
@ -6271,7 +6425,7 @@ void HistoryWidget::updateCollapseCommentsVisibility() {
|
|||
|
||||
void HistoryWidget::mousePressEvent(QMouseEvent *e) {
|
||||
_replyForwardPressed = QRect(0, _field.y() - st::sendPadding - st::replyHeight, st::replySkip, st::replyHeight).contains(e->pos());
|
||||
if (_replyForwardPressed && !_replyForwardPreviewCancel.isHidden()) {
|
||||
if (_replyForwardPressed && !_fieldBarCancel.isHidden()) {
|
||||
updateField();
|
||||
} else if (_inRecord && cHasAudioCapture()) {
|
||||
audioCapture()->start();
|
||||
|
@ -6285,8 +6439,8 @@ void HistoryWidget::mousePressEvent(QMouseEvent *e) {
|
|||
a_recordDown.start(1);
|
||||
a_recordOver.restart();
|
||||
_a_record.start();
|
||||
} else if (_inReply) {
|
||||
Ui::showPeerHistory(_peer, replyToId());
|
||||
} else if (_inReplyEdit) {
|
||||
Ui::showPeerHistory(_peer, _editMsgId ? _editMsgId : replyToId());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6615,16 +6769,25 @@ void HistoryWidget::onReplyToMessage() {
|
|||
|
||||
App::main()->cancelForwarding();
|
||||
|
||||
_replyTo = to;
|
||||
_replyToId = to->id;
|
||||
_replyToText.setText(st::msgFont, _replyTo->inDialogsText(), _textDlgOptions);
|
||||
if (_editMsgId) {
|
||||
if (!_history->msgDraft) {
|
||||
_history->setMsgDraft(new HistoryDraft(QString(), to->id, MessageCursor(), false));
|
||||
} else {
|
||||
_history->msgDraft->msgId = to->id;
|
||||
}
|
||||
} else {
|
||||
_replyEditMsg = to;
|
||||
_replyToId = to->id;
|
||||
_replyEditMsgText.setText(st::msgFont, _replyEditMsg->inDialogsText(), _textDlgOptions);
|
||||
|
||||
updateBotKeyboard();
|
||||
updateBotKeyboard();
|
||||
|
||||
if (!_field.isHidden()) _replyForwardPreviewCancel.show();
|
||||
updateReplyToName();
|
||||
resizeEvent(0);
|
||||
updateField();
|
||||
if (!_field.isHidden()) _fieldBarCancel.show();
|
||||
updateMouseTracking();
|
||||
updateReplyToName();
|
||||
resizeEvent(0);
|
||||
updateField();
|
||||
}
|
||||
|
||||
_saveDraftText = true;
|
||||
_saveDraftStart = getms();
|
||||
|
@ -6642,7 +6805,42 @@ void HistoryWidget::onEditMessage() {
|
|||
Ui::showLayer(box);
|
||||
} else {
|
||||
delete box;
|
||||
// edit post
|
||||
|
||||
if (_replyToId || !_field.getLastText().isEmpty()) {
|
||||
_history->setMsgDraft(new HistoryDraft(_field, _replyToId, _previewCancelled));
|
||||
} else {
|
||||
_history->setMsgDraft(Nil);
|
||||
}
|
||||
|
||||
QString text(textApplyEntities(to->originalText(), to->originalEntities()));
|
||||
_history->setEditDraft(new HistoryEditDraft(text, to->id, MessageCursor(text.size(), text.size(), QFIXED_MAX), false));
|
||||
applyDraft(false);
|
||||
|
||||
_previewData = 0;
|
||||
if (HistoryMedia *media = to->getMedia()) {
|
||||
if (media->type() == MediaTypeWebPage) {
|
||||
_previewData = static_cast<HistoryWebPage*>(media)->webpage();
|
||||
updatePreview();
|
||||
}
|
||||
}
|
||||
if (!_previewData) {
|
||||
onPreviewParse();
|
||||
}
|
||||
|
||||
updateBotKeyboard();
|
||||
|
||||
if (!_field.isHidden()) _fieldBarCancel.show();
|
||||
updateFieldPlaceholder();
|
||||
updateMouseTracking();
|
||||
updateReplyToName();
|
||||
resizeEvent(0);
|
||||
updateField();
|
||||
|
||||
_saveDraftText = true;
|
||||
_saveDraftStart = getms();
|
||||
onDraftSave();
|
||||
|
||||
_field.setFocus();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6652,37 +6850,77 @@ bool HistoryWidget::lastForceReplyReplied(const FullMsgId &replyTo) const {
|
|||
}
|
||||
|
||||
void HistoryWidget::cancelReply(bool lastKeyboardUsed) {
|
||||
bool wasReply = _replyToId || (_history && _history->msgDraft && _history->msgDraft->msgId);
|
||||
if (_replyToId) {
|
||||
_replyTo = 0;
|
||||
_replyEditMsg = 0;
|
||||
_replyToId = 0;
|
||||
mouseMoveEvent(0);
|
||||
if (!readyToForward() && (!_previewData || _previewData->pendingTill < 0) && !_kbReplyTo) {
|
||||
_replyForwardPreviewCancel.hide();
|
||||
_fieldBarCancel.hide();
|
||||
updateMouseTracking();
|
||||
}
|
||||
|
||||
updateBotKeyboard();
|
||||
|
||||
resizeEvent(0);
|
||||
update();
|
||||
|
||||
} else if (wasReply) {
|
||||
if (_history->msgDraft->text.isEmpty()) {
|
||||
_history->setMsgDraft(Nil);
|
||||
} else {
|
||||
_history->msgDraft->msgId = 0;
|
||||
}
|
||||
}
|
||||
if (wasReply) {
|
||||
_saveDraftText = true;
|
||||
_saveDraftStart = getms();
|
||||
onDraftSave();
|
||||
}
|
||||
if (_keyboard.singleUse() && _keyboard.forceReply() && lastKeyboardUsed) {
|
||||
if (!_editMsgId && _keyboard.singleUse() && _keyboard.forceReply() && lastKeyboardUsed) {
|
||||
if (_kbReplyTo) {
|
||||
onKbToggle(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::cancelEdit() {
|
||||
if (!_editMsgId) return;
|
||||
|
||||
_editMsgId = 0;
|
||||
_replyEditMsg = 0;
|
||||
_history->setEditDraft(Nil);
|
||||
applyDraft();
|
||||
|
||||
if (_saveEditMsgRequestId) {
|
||||
MTP::cancel(_saveEditMsgRequestId);
|
||||
_saveEditMsgRequestId = 0;
|
||||
}
|
||||
|
||||
_saveDraftText = true;
|
||||
_saveDraftStart = getms();
|
||||
onDraftSave();
|
||||
|
||||
mouseMoveEvent(0);
|
||||
if (!readyToForward() && (!_previewData || _previewData->pendingTill < 0) && !replyToId()) {
|
||||
_fieldBarCancel.hide();
|
||||
updateMouseTracking();
|
||||
}
|
||||
|
||||
onTextChange();
|
||||
updateBotKeyboard();
|
||||
updateFieldPlaceholder();
|
||||
|
||||
resizeEvent(0);
|
||||
update();
|
||||
}
|
||||
|
||||
void HistoryWidget::cancelForwarding() {
|
||||
updateControlsVisibility();
|
||||
resizeEvent(0);
|
||||
update();
|
||||
}
|
||||
|
||||
void HistoryWidget::onReplyForwardPreviewCancel() {
|
||||
void HistoryWidget::onFieldBarCancel() {
|
||||
_replyForwardPressed = false;
|
||||
if (_previewData && _previewData->pendingTill >= 0) {
|
||||
_previewCancelled = true;
|
||||
|
@ -6691,6 +6929,8 @@ void HistoryWidget::onReplyForwardPreviewCancel() {
|
|||
_saveDraftText = true;
|
||||
_saveDraftStart = getms();
|
||||
onDraftSave();
|
||||
} else if (_editMsgId) {
|
||||
cancelEdit();
|
||||
} else if (readyToForward()) {
|
||||
App::main()->cancelForwarding();
|
||||
} else if (_replyToId) {
|
||||
|
@ -6717,7 +6957,10 @@ void HistoryWidget::previewCancel() {
|
|||
_previewData = 0;
|
||||
_previewLinks.clear();
|
||||
updatePreview();
|
||||
if (!_replyToId && !readyToForward() && !_kbReplyTo) _replyForwardPreviewCancel.hide();
|
||||
if (!_editMsgId && !_replyToId && !readyToForward() && !_kbReplyTo) {
|
||||
_fieldBarCancel.hide();
|
||||
updateMouseTracking();
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::onPreviewParse() {
|
||||
|
@ -6781,7 +7024,8 @@ void HistoryWidget::gotPreview(QString links, const MTPMessageMedia &result, mtp
|
|||
void HistoryWidget::updatePreview() {
|
||||
_previewTimer.stop();
|
||||
if (_previewData && _previewData->pendingTill >= 0) {
|
||||
_replyForwardPreviewCancel.show();
|
||||
_fieldBarCancel.show();
|
||||
updateMouseTracking();
|
||||
if (_previewData->pendingTill) {
|
||||
_previewTitle.setText(st::msgServiceNameFont, lang(lng_preview_loading), _textNameOptions);
|
||||
_previewDescription.setText(st::msgFont, _previewLinks.splitRef(' ').at(0).toString(), _textDlgOptions);
|
||||
|
@ -6818,8 +7062,9 @@ void HistoryWidget::updatePreview() {
|
|||
_previewTitle.setText(st::msgServiceNameFont, title, _textNameOptions);
|
||||
_previewDescription.setText(st::msgFont, desc, _textDlgOptions);
|
||||
}
|
||||
} else if (!readyToForward() && !replyToId()) {
|
||||
_replyForwardPreviewCancel.hide();
|
||||
} else if (!readyToForward() && !replyToId() && !_editMsgId) {
|
||||
_fieldBarCancel.hide();
|
||||
updateMouseTracking();
|
||||
}
|
||||
resizeEvent(0);
|
||||
update();
|
||||
|
@ -7035,19 +7280,28 @@ void HistoryWidget::updateTopBarSelection() {
|
|||
update();
|
||||
}
|
||||
|
||||
void HistoryWidget::updateReplyTo(bool force) {
|
||||
if (!_replyToId || _replyTo) return;
|
||||
_replyTo = App::histItemById(_channel, _replyToId);
|
||||
if (_replyTo) {
|
||||
_replyToText.setText(st::msgFont, _replyTo->inDialogsText(), _textDlgOptions);
|
||||
void HistoryWidget::updateReplyEditTexts(bool force) {
|
||||
if (_replyEditMsg || (!_editMsgId && !_replyToId)) {
|
||||
return;
|
||||
}
|
||||
_replyEditMsg = App::histItemById(_channel, _editMsgId ? _editMsgId : _replyToId);
|
||||
if (_replyEditMsg) {
|
||||
_replyEditMsgText.setText(st::msgFont, _replyEditMsg->inDialogsText(), _textDlgOptions);
|
||||
|
||||
updateBotKeyboard();
|
||||
|
||||
if (!_field.isHidden() || _recording) _replyForwardPreviewCancel.show();
|
||||
if (!_field.isHidden() || _recording) {
|
||||
_fieldBarCancel.show();
|
||||
updateMouseTracking();
|
||||
}
|
||||
updateReplyToName();
|
||||
updateField();
|
||||
} else if (force) {
|
||||
cancelReply();
|
||||
if (_editMsgId) {
|
||||
cancelEdit();
|
||||
} else {
|
||||
cancelReply();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7061,9 +7315,10 @@ void HistoryWidget::updateForwarding(bool force) {
|
|||
}
|
||||
|
||||
void HistoryWidget::updateReplyToName() {
|
||||
if (!_replyTo && (_replyToId || !_kbReplyTo)) return;
|
||||
_replyToName.setText(st::msgServiceNameFont, App::peerName((_replyTo ? _replyTo : _kbReplyTo)->author()), _textNameOptions);
|
||||
_replyToNameVersion = (_replyTo ? _replyTo : _kbReplyTo)->author()->nameVersion;
|
||||
if (_editMsgId) return;
|
||||
if (!_replyEditMsg && (_replyToId || !_kbReplyTo)) return;
|
||||
_replyToName.setText(st::msgServiceNameFont, App::peerName((_replyEditMsg ? _replyEditMsg : _kbReplyTo)->author()), _textNameOptions);
|
||||
_replyToNameVersion = (_replyEditMsg ? _replyEditMsg : _kbReplyTo)->author()->nameVersion;
|
||||
}
|
||||
|
||||
void HistoryWidget::updateField() {
|
||||
|
@ -7076,9 +7331,9 @@ void HistoryWidget::drawField(Painter &p) {
|
|||
Text *from = 0, *text = 0;
|
||||
bool serviceColor = false, hasForward = readyToForward();
|
||||
ImagePtr preview;
|
||||
HistoryItem *drawReplyTo = _replyToId ? _replyTo : _kbReplyTo;
|
||||
if (_replyToId || (!hasForward && _kbReplyTo)) {
|
||||
if (drawReplyTo && drawReplyTo->author()->nameVersion > _replyToNameVersion) {
|
||||
HistoryItem *drawMsgText = (_editMsgId || _replyToId) ? _replyEditMsg : _kbReplyTo;
|
||||
if (_editMsgId || _replyToId || (!hasForward && _kbReplyTo)) {
|
||||
if (!_editMsgId && drawMsgText && drawMsgText->author()->nameVersion > _replyToNameVersion) {
|
||||
updateReplyToName();
|
||||
}
|
||||
backy -= st::replyHeight;
|
||||
|
@ -7093,27 +7348,32 @@ void HistoryWidget::drawField(Painter &p) {
|
|||
}
|
||||
bool drawPreview = (_previewData && _previewData->pendingTill >= 0) && !_replyForwardPressed;
|
||||
p.fillRect(0, backy, width(), backh, st::taMsgField.bgColor->b);
|
||||
if (_replyToId || (!hasForward && _kbReplyTo)) {
|
||||
if (_editMsgId || _replyToId || (!hasForward && _kbReplyTo)) {
|
||||
int32 replyLeft = st::replySkip;
|
||||
p.drawPixmap(QPoint(st::replyIconPos.x(), backy + st::replyIconPos.y()), App::sprite(), st::replyIcon);
|
||||
p.drawPixmap(QPoint(st::replyIconPos.x(), backy + st::replyIconPos.y()), App::sprite(), _editMsgId ? st::editIcon : st::replyIcon);
|
||||
if (!drawPreview) {
|
||||
if (drawReplyTo) {
|
||||
if (drawReplyTo->getMedia() && drawReplyTo->getMedia()->hasReplyPreview()) {
|
||||
ImagePtr replyPreview = drawReplyTo->getMedia()->replyPreview();
|
||||
if (drawMsgText) {
|
||||
if (drawMsgText->getMedia() && drawMsgText->getMedia()->hasReplyPreview()) {
|
||||
ImagePtr replyPreview = drawMsgText->getMedia()->replyPreview();
|
||||
if (!replyPreview->isNull()) {
|
||||
QRect to(replyLeft, backy + st::msgReplyPadding.top(), st::msgReplyBarSize.height(), st::msgReplyBarSize.height());
|
||||
p.drawPixmap(to.x(), to.y(), replyPreview->pixSingle(replyPreview->width() / cIntRetinaFactor(), replyPreview->height() / cIntRetinaFactor(), to.width(), to.height()));
|
||||
}
|
||||
replyLeft += st::msgReplyBarSize.height() + st::msgReplyBarSkip - st::msgReplyBarSize.width() - st::msgReplyBarPos.x();
|
||||
}
|
||||
p.setPen(st::replyColor->p);
|
||||
_replyToName.drawElided(p, replyLeft, backy + st::msgReplyPadding.top(), width() - replyLeft - _replyForwardPreviewCancel.width() - st::msgReplyPadding.right());
|
||||
p.setPen((((drawReplyTo->toHistoryMessage() && drawReplyTo->toHistoryMessage()->emptyText()) || drawReplyTo->serviceMsg()) ? st::msgInDateFg : st::msgColor)->p);
|
||||
_replyToText.drawElided(p, replyLeft, backy + st::msgReplyPadding.top() + st::msgServiceNameFont->height, width() - replyLeft - _replyForwardPreviewCancel.width() - st::msgReplyPadding.right());
|
||||
p.setPen(st::replyColor);
|
||||
if (_editMsgId) {
|
||||
p.setFont(st::msgServiceNameFont);
|
||||
p.drawText(replyLeft, backy + st::msgReplyPadding.top() + st::msgServiceNameFont->ascent, lang(lng_edit_message));
|
||||
} else {
|
||||
_replyToName.drawElided(p, replyLeft, backy + st::msgReplyPadding.top(), width() - replyLeft - _fieldBarCancel.width() - st::msgReplyPadding.right());
|
||||
}
|
||||
p.setPen((((drawMsgText->toHistoryMessage() && drawMsgText->toHistoryMessage()->emptyText()) || drawMsgText->serviceMsg()) ? st::msgInDateFg : st::msgColor)->p);
|
||||
_replyEditMsgText.drawElided(p, replyLeft, backy + st::msgReplyPadding.top() + st::msgServiceNameFont->height, width() - replyLeft - _fieldBarCancel.width() - st::msgReplyPadding.right());
|
||||
} else {
|
||||
p.setFont(st::msgDateFont->f);
|
||||
p.setPen(st::msgInDateFg->p);
|
||||
p.drawText(replyLeft, backy + st::msgReplyPadding.top() + (st::msgReplyBarSize.height() - st::msgDateFont->height) / 2 + st::msgDateFont->ascent, st::msgDateFont->elided(lang(lng_profile_loading), width() - replyLeft - _replyForwardPreviewCancel.width() - st::msgReplyPadding.right()));
|
||||
p.drawText(replyLeft, backy + st::msgReplyPadding.top() + (st::msgReplyBarSize.height() - st::msgDateFont->height) / 2 + st::msgDateFont->ascent, st::msgDateFont->elided(lang(lng_profile_loading), width() - replyLeft - _fieldBarCancel.width() - st::msgReplyPadding.right()));
|
||||
}
|
||||
}
|
||||
} else if (from && text) {
|
||||
|
@ -7131,9 +7391,9 @@ void HistoryWidget::drawField(Painter &p) {
|
|||
forwardLeft += st::msgReplyBarSize.height() + st::msgReplyBarSkip - st::msgReplyBarSize.width() - st::msgReplyBarPos.x();
|
||||
}
|
||||
p.setPen(st::replyColor->p);
|
||||
from->drawElided(p, forwardLeft, backy + st::msgReplyPadding.top(), width() - forwardLeft - _replyForwardPreviewCancel.width() - st::msgReplyPadding.right());
|
||||
from->drawElided(p, forwardLeft, backy + st::msgReplyPadding.top(), width() - forwardLeft - _fieldBarCancel.width() - st::msgReplyPadding.right());
|
||||
p.setPen((serviceColor ? st::msgInDateFg : st::msgColor)->p);
|
||||
text->drawElided(p, forwardLeft, backy + st::msgReplyPadding.top() + st::msgServiceNameFont->height, width() - forwardLeft - _replyForwardPreviewCancel.width() - st::msgReplyPadding.right());
|
||||
text->drawElided(p, forwardLeft, backy + st::msgReplyPadding.top() + st::msgServiceNameFont->height, width() - forwardLeft - _fieldBarCancel.width() - st::msgReplyPadding.right());
|
||||
}
|
||||
}
|
||||
if (drawPreview) {
|
||||
|
@ -7153,9 +7413,9 @@ void HistoryWidget::drawField(Painter &p) {
|
|||
previewLeft += st::msgReplyBarSize.height() + st::msgReplyBarSkip - st::msgReplyBarSize.width() - st::msgReplyBarPos.x();
|
||||
}
|
||||
p.setPen(st::replyColor->p);
|
||||
_previewTitle.drawElided(p, previewLeft, backy + st::msgReplyPadding.top(), width() - previewLeft - _replyForwardPreviewCancel.width() - st::msgReplyPadding.right());
|
||||
_previewTitle.drawElided(p, previewLeft, backy + st::msgReplyPadding.top(), width() - previewLeft - _fieldBarCancel.width() - st::msgReplyPadding.right());
|
||||
p.setPen(st::msgColor->p);
|
||||
_previewDescription.drawElided(p, previewLeft, backy + st::msgReplyPadding.top() + st::msgServiceNameFont->height, width() - previewLeft - _replyForwardPreviewCancel.width() - st::msgReplyPadding.right());
|
||||
_previewDescription.drawElided(p, previewLeft, backy + st::msgReplyPadding.top() + st::msgServiceNameFont->height, width() - previewLeft - _fieldBarCancel.width() - st::msgReplyPadding.right());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -505,9 +505,10 @@ public:
|
|||
void updateScrollColors();
|
||||
|
||||
MsgId replyToId() const;
|
||||
void updateReplyTo(bool force = false);
|
||||
void updateReplyEditTexts(bool force = false);
|
||||
bool lastForceReplyReplied(const FullMsgId &replyTo = FullMsgId(NoChannel, -1)) const;
|
||||
void cancelReply(bool lastKeyboardUsed = false);
|
||||
void cancelEdit();
|
||||
void updateForwarding(bool force = false);
|
||||
void cancelForwarding(); // called by MainWidget
|
||||
|
||||
|
@ -595,7 +596,7 @@ public slots:
|
|||
void onCancel();
|
||||
void onReplyToMessage();
|
||||
void onEditMessage();
|
||||
void onReplyForwardPreviewCancel();
|
||||
void onFieldBarCancel();
|
||||
|
||||
void onCancelSendAction();
|
||||
|
||||
|
@ -689,12 +690,17 @@ public slots:
|
|||
private:
|
||||
|
||||
MsgId _replyToId;
|
||||
HistoryItem *_replyTo;
|
||||
Text _replyToName, _replyToText;
|
||||
Text _replyToName;
|
||||
int32 _replyToNameVersion;
|
||||
IconedButton _replyForwardPreviewCancel;
|
||||
void updateReplyToName();
|
||||
|
||||
MsgId _editMsgId;
|
||||
|
||||
HistoryItem *_replyEditMsg;
|
||||
Text _replyEditMsgText;
|
||||
|
||||
IconedButton _fieldBarCancel;
|
||||
|
||||
void sendExistingDocument(DocumentData *doc, const QString &caption);
|
||||
void sendExistingPhoto(PhotoData *photo, const QString &caption);
|
||||
|
||||
|
@ -702,6 +708,13 @@ private:
|
|||
void drawRecordButton(Painter &p);
|
||||
void drawRecording(Painter &p);
|
||||
|
||||
void updateMouseTracking();
|
||||
|
||||
mtpRequestId _saveEditMsgRequestId;
|
||||
void saveEditMsg();
|
||||
void saveEditMsgDone(History *history, const MTPUpdates &updates, mtpRequestId req);
|
||||
bool saveEditMsgFail(History *history, const RPCError &error, mtpRequestId req);
|
||||
|
||||
DBIPeerReportSpamStatus _reportSpamStatus;
|
||||
void updateReportSpamStatus();
|
||||
|
||||
|
@ -747,7 +760,8 @@ private:
|
|||
void savedGifsGot(const MTPmessages_SavedGifs &gifs);
|
||||
bool savedGifsFailed(const RPCError &error);
|
||||
|
||||
void writeDraft(MsgId *replyTo = 0, const QString *text = 0, const MessageCursor *cursor = 0, bool *previewCancelled = 0);
|
||||
void writeDrafts(HistoryDraft **msgDraft, HistoryEditDraft **editDraft);
|
||||
void writeDrafts(History *history);
|
||||
void setFieldText(const QString &text, int32 textUpdateEventsFlags = 0, bool clearUndoHistory = true);
|
||||
|
||||
QStringList getMediasFromMime(const QMimeData *d);
|
||||
|
@ -806,7 +820,7 @@ private:
|
|||
bool _cmdStartShown;
|
||||
MessageField _field;
|
||||
Animation _a_record, _a_recording;
|
||||
bool _recording, _inRecord, _inField, _inReply;
|
||||
bool _recording, _inRecord, _inField, _inReplyEdit;
|
||||
anim::ivalue a_recordingLevel;
|
||||
int32 _recordingSamples;
|
||||
anim::fvalue a_recordOver, a_recordDown;
|
||||
|
|
|
@ -557,7 +557,7 @@ namespace {
|
|||
};
|
||||
|
||||
typedef QMap<PeerId, FileKey> DraftsMap;
|
||||
DraftsMap _draftsMap, _draftsPositionsMap;
|
||||
DraftsMap _draftsMap, _draftCursorsMap;
|
||||
typedef QMap<PeerId, bool> DraftsNotReadMap;
|
||||
DraftsNotReadMap _draftsNotReadMap;
|
||||
|
||||
|
@ -1672,7 +1672,7 @@ namespace {
|
|||
}
|
||||
LOG(("App Info: reading encrypted map.."));
|
||||
|
||||
DraftsMap draftsMap, draftsPositionsMap;
|
||||
DraftsMap draftsMap, draftCursorsMap;
|
||||
DraftsNotReadMap draftsNotReadMap;
|
||||
StorageMap imagesMap, stickerImagesMap, audiosMap;
|
||||
qint64 storageImagesSize = 0, storageStickersSize = 0, storageAudiosSize = 0;
|
||||
|
@ -1701,7 +1701,7 @@ namespace {
|
|||
FileKey key;
|
||||
quint64 p;
|
||||
map.stream >> key >> p;
|
||||
draftsPositionsMap.insert(p, key);
|
||||
draftCursorsMap.insert(p, key);
|
||||
}
|
||||
} break;
|
||||
case lskImages: {
|
||||
|
@ -1781,7 +1781,7 @@ namespace {
|
|||
}
|
||||
|
||||
_draftsMap = draftsMap;
|
||||
_draftsPositionsMap = draftsPositionsMap;
|
||||
_draftCursorsMap = draftCursorsMap;
|
||||
_draftsNotReadMap = draftsNotReadMap;
|
||||
|
||||
_imagesMap = imagesMap;
|
||||
|
@ -1860,7 +1860,7 @@ namespace {
|
|||
|
||||
uint32 mapSize = 0;
|
||||
if (!_draftsMap.isEmpty()) mapSize += sizeof(quint32) * 2 + _draftsMap.size() * sizeof(quint64) * 2;
|
||||
if (!_draftsPositionsMap.isEmpty()) mapSize += sizeof(quint32) * 2 + _draftsPositionsMap.size() * sizeof(quint64) * 2;
|
||||
if (!_draftCursorsMap.isEmpty()) mapSize += sizeof(quint32) * 2 + _draftCursorsMap.size() * sizeof(quint64) * 2;
|
||||
if (!_imagesMap.isEmpty()) mapSize += sizeof(quint32) * 2 + _imagesMap.size() * (sizeof(quint64) * 3 + sizeof(qint32));
|
||||
if (!_stickerImagesMap.isEmpty()) mapSize += sizeof(quint32) * 2 + _stickerImagesMap.size() * (sizeof(quint64) * 3 + sizeof(qint32));
|
||||
if (!_audiosMap.isEmpty()) mapSize += sizeof(quint32) * 2 + _audiosMap.size() * (sizeof(quint64) * 3 + sizeof(qint32));
|
||||
|
@ -1880,9 +1880,9 @@ namespace {
|
|||
mapData.stream << quint64(i.value()) << quint64(i.key());
|
||||
}
|
||||
}
|
||||
if (!_draftsPositionsMap.isEmpty()) {
|
||||
mapData.stream << quint32(lskDraftPosition) << quint32(_draftsPositionsMap.size());
|
||||
for (DraftsMap::const_iterator i = _draftsPositionsMap.cbegin(), e = _draftsPositionsMap.cend(); i != e; ++i) {
|
||||
if (!_draftCursorsMap.isEmpty()) {
|
||||
mapData.stream << quint32(lskDraftPosition) << quint32(_draftCursorsMap.size());
|
||||
for (DraftsMap::const_iterator i = _draftCursorsMap.cbegin(), e = _draftCursorsMap.cend(); i != e; ++i) {
|
||||
mapData.stream << quint64(i.value()) << quint64(i.key());
|
||||
}
|
||||
}
|
||||
|
@ -2180,7 +2180,7 @@ namespace Local {
|
|||
|
||||
_passKeySalt.clear(); // reset passcode, local key
|
||||
_draftsMap.clear();
|
||||
_draftsPositionsMap.clear();
|
||||
_draftCursorsMap.clear();
|
||||
_fileLocations.clear();
|
||||
_fileLocationPairs.clear();
|
||||
_fileLocationAliases.clear();
|
||||
|
@ -2237,10 +2237,10 @@ namespace Local {
|
|||
return _oldSettingsVersion;
|
||||
}
|
||||
|
||||
void writeDraft(const PeerId &peer, const MessageDraft &draft) {
|
||||
void writeDrafts(const PeerId &peer, const MessageDraft &msgDraft, const MessageDraft &editDraft) {
|
||||
if (!_working()) return;
|
||||
|
||||
if (draft.replyTo <= 0 && draft.text.isEmpty()) {
|
||||
if (msgDraft.msgId <= 0 && msgDraft.text.isEmpty() && editDraft.msgId <= 0) {
|
||||
DraftsMap::iterator i = _draftsMap.find(peer);
|
||||
if (i != _draftsMap.cend()) {
|
||||
clearKey(i.value());
|
||||
|
@ -2257,8 +2257,12 @@ namespace Local {
|
|||
_mapChanged = true;
|
||||
_writeMap(WriteMapFast);
|
||||
}
|
||||
EncryptedDescriptor data(sizeof(quint64) + _stringSize(draft.text) + sizeof(qint32));
|
||||
data.stream << quint64(peer) << draft.text << qint32(draft.replyTo) << qint32(draft.previewCancelled ? 1 : 0);
|
||||
|
||||
EncryptedDescriptor data(sizeof(quint64) + _stringSize(msgDraft.text) + 2 * sizeof(qint32) + _stringSize(editDraft.text) + 2 * sizeof(qint32));
|
||||
data.stream << quint64(peer);
|
||||
data.stream << msgDraft.text << qint32(msgDraft.msgId) << qint32(msgDraft.previewCancelled ? 1 : 0);
|
||||
data.stream << editDraft.text << qint32(editDraft.msgId) << qint32(editDraft.previewCancelled ? 1 : 0);
|
||||
|
||||
FileWriteDescriptor file(i.value());
|
||||
file.writeEncrypted(data);
|
||||
|
||||
|
@ -2266,75 +2270,123 @@ namespace Local {
|
|||
}
|
||||
}
|
||||
|
||||
MessageDraft readDraft(const PeerId &peer) {
|
||||
if (!_draftsNotReadMap.remove(peer)) return MessageDraft();
|
||||
void clearDraftCursors(const PeerId &peer) {
|
||||
DraftsMap::iterator i = _draftCursorsMap.find(peer);
|
||||
if (i != _draftCursorsMap.cend()) {
|
||||
clearKey(i.value());
|
||||
_draftCursorsMap.erase(i);
|
||||
_mapChanged = true;
|
||||
_writeMap();
|
||||
}
|
||||
}
|
||||
|
||||
void _readDraftCursors(const PeerId &peer, MessageCursor &msgCursor, MessageCursor &editCursor) {
|
||||
DraftsMap::iterator j = _draftCursorsMap.find(peer);
|
||||
if (j == _draftCursorsMap.cend()) {
|
||||
return;
|
||||
}
|
||||
|
||||
FileReadDescriptor draft;
|
||||
if (!readEncryptedFile(draft, j.value())) {
|
||||
clearDraftCursors(peer);
|
||||
return;
|
||||
}
|
||||
quint64 draftPeer;
|
||||
qint32 msgPosition = 0, msgAnchor = 0, msgScroll = QFIXED_MAX;
|
||||
qint32 editPosition = 0, editAnchor = 0, editScroll = QFIXED_MAX;
|
||||
draft.stream >> draftPeer >> msgPosition >> msgAnchor >> msgScroll;
|
||||
if (!draft.stream.atEnd()) {
|
||||
draft.stream >> editPosition >> editAnchor >> editScroll;
|
||||
}
|
||||
|
||||
if (draftPeer != peer) {
|
||||
clearDraftCursors(peer);
|
||||
return;
|
||||
}
|
||||
|
||||
msgCursor = MessageCursor(msgPosition, msgAnchor, msgScroll);
|
||||
editCursor = MessageCursor(editPosition, editAnchor, editScroll);
|
||||
}
|
||||
|
||||
void readDraftsWithCursors(History *h) {
|
||||
PeerId peer = h->peer->id;
|
||||
if (!_draftsNotReadMap.remove(peer)) {
|
||||
clearDraftCursors(peer);
|
||||
return;
|
||||
}
|
||||
|
||||
DraftsMap::iterator j = _draftsMap.find(peer);
|
||||
if (j == _draftsMap.cend()) {
|
||||
return MessageDraft();
|
||||
clearDraftCursors(peer);
|
||||
return;
|
||||
}
|
||||
FileReadDescriptor draft;
|
||||
if (!readEncryptedFile(draft, j.value())) {
|
||||
clearKey(j.value());
|
||||
_draftsMap.erase(j);
|
||||
return MessageDraft();
|
||||
clearDraftCursors(peer);
|
||||
return;
|
||||
}
|
||||
|
||||
quint64 draftPeer;
|
||||
QString draftText;
|
||||
qint32 draftReplyTo = 0, draftPreviewCancelled = 0;
|
||||
draft.stream >> draftPeer >> draftText;
|
||||
if (draft.version >= 7021) draft.stream >> draftReplyTo;
|
||||
if (draft.version >= 8001) draft.stream >> draftPreviewCancelled;
|
||||
return (draftPeer == peer) ? MessageDraft(MsgId(draftReplyTo), draftText, (draftPreviewCancelled == 1)) : MessageDraft();
|
||||
quint64 draftPeer = 0;
|
||||
QString msgText, editText;
|
||||
qint32 msgReplyTo = 0, msgPreviewCancelled = 0, editMsgId = 0, editPreviewCancelled = 0;
|
||||
draft.stream >> draftPeer >> msgText;
|
||||
if (draft.version >= 7021) {
|
||||
draft.stream >> msgReplyTo;
|
||||
if (draft.version >= 8001) {
|
||||
draft.stream >> msgPreviewCancelled;
|
||||
if (!draft.stream.atEnd()) {
|
||||
draft.stream >> editText >> editMsgId >> editPreviewCancelled;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (draftPeer != peer) {
|
||||
clearKey(j.value());
|
||||
_draftsMap.erase(j);
|
||||
clearDraftCursors(peer);
|
||||
return;
|
||||
}
|
||||
|
||||
MessageCursor msgCursor, editCursor;
|
||||
_readDraftCursors(peer, msgCursor, editCursor);
|
||||
|
||||
if (msgText.isEmpty() && !msgReplyTo) {
|
||||
h->setMsgDraft(Nil);
|
||||
} else {
|
||||
h->setMsgDraft(new HistoryDraft(msgText, msgReplyTo, msgCursor, msgPreviewCancelled));
|
||||
}
|
||||
if (!editMsgId) {
|
||||
h->setEditDraft(Nil);
|
||||
} else {
|
||||
h->setEditDraft(new HistoryEditDraft(editText, editMsgId, editCursor, editPreviewCancelled));
|
||||
}
|
||||
}
|
||||
|
||||
void writeDraftPositions(const PeerId &peer, const MessageCursor &cur) {
|
||||
void writeDraftCursors(const PeerId &peer, const MessageCursor &msgCursor, const MessageCursor &editCursor) {
|
||||
if (!_working()) return;
|
||||
|
||||
if (cur.position == 0 && cur.anchor == 0 && cur.scroll == QFIXED_MAX) {
|
||||
DraftsMap::iterator i = _draftsPositionsMap.find(peer);
|
||||
if (i != _draftsPositionsMap.cend()) {
|
||||
clearKey(i.value());
|
||||
_draftsPositionsMap.erase(i);
|
||||
_mapChanged = true;
|
||||
_writeMap();
|
||||
}
|
||||
if (msgCursor == MessageCursor() && editCursor == MessageCursor()) {
|
||||
clearDraftCursors(peer);
|
||||
} else {
|
||||
DraftsMap::const_iterator i = _draftsPositionsMap.constFind(peer);
|
||||
if (i == _draftsPositionsMap.cend()) {
|
||||
i = _draftsPositionsMap.insert(peer, genKey());
|
||||
DraftsMap::const_iterator i = _draftCursorsMap.constFind(peer);
|
||||
if (i == _draftCursorsMap.cend()) {
|
||||
i = _draftCursorsMap.insert(peer, genKey());
|
||||
_mapChanged = true;
|
||||
_writeMap(WriteMapFast);
|
||||
}
|
||||
|
||||
EncryptedDescriptor data(sizeof(quint64) + sizeof(qint32) * 3);
|
||||
data.stream << quint64(peer) << qint32(cur.position) << qint32(cur.anchor) << qint32(cur.scroll);
|
||||
data.stream << quint64(peer) << qint32(msgCursor.position) << qint32(msgCursor.anchor) << qint32(msgCursor.scroll);
|
||||
data.stream << qint32(editCursor.position) << qint32(editCursor.anchor) << qint32(editCursor.scroll);
|
||||
|
||||
FileWriteDescriptor file(i.value());
|
||||
file.writeEncrypted(data);
|
||||
}
|
||||
}
|
||||
|
||||
MessageCursor readDraftPositions(const PeerId &peer) {
|
||||
DraftsMap::iterator j = _draftsPositionsMap.find(peer);
|
||||
if (j == _draftsPositionsMap.cend()) {
|
||||
return MessageCursor();
|
||||
}
|
||||
FileReadDescriptor draft;
|
||||
if (!readEncryptedFile(draft, j.value())) {
|
||||
clearKey(j.value());
|
||||
_draftsPositionsMap.erase(j);
|
||||
return MessageCursor();
|
||||
}
|
||||
|
||||
quint64 draftPeer;
|
||||
qint32 curPosition, curAnchor, curScroll;
|
||||
draft.stream >> draftPeer >> curPosition >> curAnchor >> curScroll;
|
||||
|
||||
return (draftPeer == peer) ? MessageCursor(curPosition, curAnchor, curScroll) : MessageCursor();
|
||||
}
|
||||
|
||||
bool hasDraftPositions(const PeerId &peer) {
|
||||
return (_draftsPositionsMap.constFind(peer) != _draftsPositionsMap.cend());
|
||||
bool hasDraftCursors(const PeerId &peer) {
|
||||
return (_draftCursorsMap.constFind(peer) != _draftCursorsMap.cend());
|
||||
}
|
||||
|
||||
void writeFileLocation(MediaKey location, const FileLocation &local) {
|
||||
|
@ -3795,8 +3847,8 @@ namespace Local {
|
|||
_draftsMap.clear();
|
||||
_mapChanged = true;
|
||||
}
|
||||
if (!_draftsPositionsMap.isEmpty()) {
|
||||
_draftsPositionsMap.clear();
|
||||
if (!_draftCursorsMap.isEmpty()) {
|
||||
_draftCursorsMap.clear();
|
||||
_mapChanged = true;
|
||||
}
|
||||
if (_locationsKey) {
|
||||
|
|
|
@ -106,17 +106,16 @@ namespace Local {
|
|||
int32 oldSettingsVersion();
|
||||
|
||||
struct MessageDraft {
|
||||
MessageDraft(MsgId replyTo = 0, QString text = QString(), bool previewCancelled = false) : replyTo(replyTo), text(text), previewCancelled(previewCancelled) {
|
||||
MessageDraft(MsgId msgId = 0, QString text = QString(), bool previewCancelled = false) : msgId(msgId), text(text), previewCancelled(previewCancelled) {
|
||||
}
|
||||
MsgId replyTo;
|
||||
MsgId msgId;
|
||||
QString text;
|
||||
bool previewCancelled;
|
||||
};
|
||||
void writeDraft(const PeerId &peer, const MessageDraft &draft);
|
||||
MessageDraft readDraft(const PeerId &peer);
|
||||
void writeDraftPositions(const PeerId &peer, const MessageCursor &cur);
|
||||
MessageCursor readDraftPositions(const PeerId &peer);
|
||||
bool hasDraftPositions(const PeerId &peer);
|
||||
void writeDrafts(const PeerId &peer, const MessageDraft &msgDraft, const MessageDraft &editDraft);
|
||||
void readDraftsWithCursors(History *h);
|
||||
void writeDraftCursors(const PeerId &peer, const MessageCursor &msgCursor, const MessageCursor &editCursor);
|
||||
bool hasDraftCursors(const PeerId &peer);
|
||||
|
||||
void writeFileLocation(MediaKey location, const FileLocation &local);
|
||||
FileLocation readFileLocation(MediaKey location, bool check = true);
|
||||
|
|
|
@ -516,10 +516,8 @@ bool MainWidget::onShareUrl(const PeerId &peer, const QString &url, const QStrin
|
|||
return false;
|
||||
}
|
||||
History *h = App::history(peer);
|
||||
h->draft = url + '\n' + text;
|
||||
h->draftCursor.anchor = url.size() + 1;
|
||||
h->draftCursor.position = h->draftCursor.anchor + text.size();
|
||||
h->draftPreviewCancelled = false;
|
||||
h->setMsgDraft(new HistoryDraft(url + '\n' + text, 0, MessageCursor(url.size() + 1, url.size() + 1 + text.size(), QFIXED_MAX), false));
|
||||
h->setEditDraft(Nil);
|
||||
bool opened = history.peer() && (history.peer()->id == peer);
|
||||
if (opened) {
|
||||
history.applyDraft();
|
||||
|
@ -2039,7 +2037,7 @@ ApiWrap *MainWidget::api() {
|
|||
}
|
||||
|
||||
void MainWidget::updateReplyTo() {
|
||||
history.updateReplyTo(true);
|
||||
history.updateReplyEditTexts(true);
|
||||
}
|
||||
|
||||
void MainWidget::updateBotKeyboard(History *h) {
|
||||
|
|
|
@ -1217,3 +1217,7 @@ struct MessageCursor {
|
|||
}
|
||||
int position, anchor, scroll;
|
||||
};
|
||||
|
||||
inline bool operator==(const MessageCursor &a, const MessageCursor &b) {
|
||||
return (a.position == b.position) && (a.anchor == b.anchor) && (a.scroll == b.scroll);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,8 @@ uint64 _SharedMemoryLocation[4] = { 0x00, 0x01, 0x02, 0x03 };
|
|||
|
||||
// Base types compile-time check
|
||||
|
||||
NilPointer Nil;
|
||||
|
||||
namespace {
|
||||
template <typename T, int N>
|
||||
class _TypeSizeCheckerHelper {
|
||||
|
|
|
@ -36,6 +36,22 @@ T *exchange(T *&ptr) {
|
|||
struct NullType {
|
||||
};
|
||||
|
||||
class NilPointer {
|
||||
public:
|
||||
template <typename T>
|
||||
operator T*() const {
|
||||
return 0;
|
||||
}
|
||||
template <typename C, typename T>
|
||||
operator T C::*() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
void operator&() const;
|
||||
};
|
||||
extern NilPointer Nil;
|
||||
|
||||
template <typename T>
|
||||
class OrderedSet : public QMap<T, NullType> {
|
||||
public:
|
||||
|
|
|
@ -34,8 +34,8 @@ IDI_ICON1 ICON "SourceFiles\\art\\icon256.ico"
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 0,9,26,0
|
||||
PRODUCTVERSION 0,9,26,0
|
||||
FILEVERSION 0,9,26,1
|
||||
PRODUCTVERSION 0,9,26,1
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -51,10 +51,10 @@ BEGIN
|
|||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Telegram Messenger LLP"
|
||||
VALUE "FileVersion", "0.9.26.0"
|
||||
VALUE "FileVersion", "0.9.26.1"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2016"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "0.9.26.0"
|
||||
VALUE "ProductVersion", "0.9.26.1"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -1739,7 +1739,7 @@
|
|||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
CURRENT_PROJECT_VERSION = 0.9.25;
|
||||
CURRENT_PROJECT_VERSION = 0.9.26;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = fast;
|
||||
GCC_PREFIX_HEADER = ./SourceFiles/stdafx.h;
|
||||
|
@ -1768,10 +1768,10 @@
|
|||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 0.9.25;
|
||||
CURRENT_PROJECT_VERSION = 0.9.26;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DYLIB_COMPATIBILITY_VERSION = 0.9;
|
||||
DYLIB_CURRENT_VERSION = 0.9.25;
|
||||
DYLIB_CURRENT_VERSION = 0.9.26;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = "";
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
|
@ -1909,10 +1909,10 @@
|
|||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 0.9.25;
|
||||
CURRENT_PROJECT_VERSION = 0.9.26;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DYLIB_COMPATIBILITY_VERSION = 0.9;
|
||||
DYLIB_CURRENT_VERSION = 0.9.25;
|
||||
DYLIB_CURRENT_VERSION = 0.9.26;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = "";
|
||||
|
|
|
@ -3,4 +3,4 @@ AppVersionStrMajor 0.9
|
|||
AppVersionStrSmall 0.9.26
|
||||
AppVersionStr 0.9.26
|
||||
DevChannel 0
|
||||
BetaVersion 0 9019002
|
||||
BetaVersion 9026001
|
||||
|
|
Loading…
Add table
Reference in a new issue