forward/delete for channels, prepared load unread by offset_id, not done yet!

This commit is contained in:
John Preston 2015-09-07 10:52:37 +03:00
parent b53e35e046
commit 54d5b6dd71
14 changed files with 205 additions and 107 deletions

View File

@ -584,6 +584,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_send_image_compressed" = "Send compressed image";
"lng_forward_choose" = "Choose recipient..";
"lng_forward_cant" = "Sorry, no way to forward here :(";
"lng_forward_confirm" = "Forward to {recipient}?";
"lng_forward_share_contact" = "Share contact to {recipient}?";
"lng_forward_send_file_confirm" = "Send «{name}» to {recipient}?";

View File

@ -1580,16 +1580,20 @@ namespace App {
return ::histories;
}
History *history(const PeerId &peer, int32 unreadCnt, int32 maxInboxRead) {
History *history(const PeerId &peer) {
Histories::const_iterator i = ::histories.constFind(peer);
if (i == ::histories.cend()) {
i = App::histories().insert(peer, new History(peer));
}
return i.value();
}
History *historyFromDialog(const PeerId &peer, int32 unreadCnt, int32 maxInboxRead) {
Histories::const_iterator i = ::histories.constFind(peer);
if (i == ::histories.cend()) {
i = App::histories().insert(peer, new History(peer));
i.value()->setUnreadCount(unreadCnt, false);
if (maxInboxRead) {
i.value()->inboxReadTill = maxInboxRead;
}
} else if (maxInboxRead) {
i.value()->inboxReadTill = qMax(i.value()->inboxReadTill, maxInboxRead);
i.value()->inboxReadBefore = maxInboxRead + 1;
}
return i.value();
}

View File

@ -166,7 +166,8 @@ namespace App {
MTPPhoto photoFromUserPhoto(MTPint userId, MTPint date, const MTPUserProfilePhoto &photo);
Histories &histories();
History *history(const PeerId &peer, int32 unreadCnt = 0, int32 maxInboxRead = 0);
History *history(const PeerId &peer);
History *historyFromDialog(const PeerId &peer, int32 unreadCnt, int32 maxInboxRead);
History *historyLoaded(const PeerId &peer);
HistoryItem *histItemById(ChannelId channelId, MsgId itemId);
inline HistoryItem *histItemById(const FullMsgId &msgId) {

View File

@ -761,11 +761,29 @@ void DialogsListWidget::itemRemoved(HistoryItem *item) {
void DialogsListWidget::dialogsReceived(const QVector<MTPDialog> &added) {
for (QVector<MTPDialog>::const_iterator i = added.cbegin(), e = added.cend(); i != e; ++i) {
History *history = 0;
switch (i->type()) {
case mtpc_dialog: addDialog(i->c_dialog()); break;
case mtpc_dialogChannel: addDialogChannel(i->c_dialogChannel()); break;
case mtpc_dialog: {
const MTPDdialog &d(i->c_dialog());
history = App::historyFromDialog(peerFromMTP(d.vpeer), d.vunread_count.v, d.vread_inbox_max_id.v);
App::main()->applyNotifySetting(MTP_notifyPeer(d.vpeer), d.vnotify_settings, history);
} break;
case mtpc_dialogChannel: {
const MTPDdialogChannel &d(i->c_dialogChannel());
History *history = App::historyFromDialog(peerFromMTP(d.vpeer), d.vunread_important_count.v, d.vread_inbox_max_id.v);
App::main()->applyNotifySetting(MTP_notifyPeer(d.vpeer), d.vnotify_settings, history);
} break;
}
if (history) {
if (!history->lastMsgDate.isNull()) addSavedPeersAfter(history->lastMsgDate);
History::DialogLinks links = dialogs.addToEnd(history);
history->dialogs = links;
contactsNoDialogs.del(history->peer);
}
}
if (App::wnd()) App::wnd()->updateCounter();
if (!sel && dialogs.list.count) {
sel = dialogs.list.begin;
@ -948,7 +966,7 @@ void DialogsListWidget::clearFilter() {
}
void DialogsListWidget::addDialog(const MTPDdialog &dialog) {
History *history = App::history(peerFromMTP(dialog.vpeer), dialog.vunread_count.v, dialog.vread_inbox_max_id.v);
History *history = App::historyFromDialog(peerFromMTP(dialog.vpeer), dialog.vunread_count.v, dialog.vread_inbox_max_id.v);
if (!history->lastMsgDate.isNull()) addSavedPeersAfter(history->lastMsgDate);
History::DialogLinks links = dialogs.addToEnd(history);
@ -959,7 +977,7 @@ void DialogsListWidget::addDialog(const MTPDdialog &dialog) {
}
void DialogsListWidget::addDialogChannel(const MTPDdialogChannel &dialogChannel) {
History *history = App::history(peerFromMTP(dialogChannel.vpeer), dialogChannel.vunread_important_count.v, dialogChannel.vread_inbox_max_id.v);
History *history = App::historyFromDialog(peerFromMTP(dialogChannel.vpeer), dialogChannel.vunread_important_count.v, dialogChannel.vread_inbox_max_id.v);
if (!history->lastMsgDate.isNull()) addSavedPeersAfter(history->lastMsgDate);
History::DialogLinks links = dialogs.addToEnd(history);
@ -1603,6 +1621,7 @@ void DialogsWidget::unreadCountsReceived(const QVector<MTPDialog> &dialogs) {
App::main()->applyNotifySetting(MTP_notifyPeer(d.vpeer), d.vnotify_settings, j.value());
if (d.vunread_count.v >= j.value()->unreadCount) {
j.value()->setUnreadCount(d.vunread_count.v, false);
j.value()->inboxReadBefore = d.vread_inbox_max_id.v + 1;
}
}
} break;
@ -1613,6 +1632,7 @@ void DialogsWidget::unreadCountsReceived(const QVector<MTPDialog> &dialogs) {
App::main()->applyNotifySetting(MTP_notifyPeer(d.vpeer), d.vnotify_settings, j.value());
if (d.vunread_important_count.v >= j.value()->unreadCount) {
j.value()->setUnreadCount(d.vunread_important_count.v, false);
j.value()->inboxReadBefore = d.vread_inbox_max_id.v + 1;
}
}
} break;

View File

@ -303,8 +303,8 @@ void FakeDialogRow::paint(QPainter &p, int32 w, bool act, bool sel) const {
History::History(const PeerId &peerId) : width(0), height(0)
, msgCount(0)
, unreadCount(0)
, inboxReadTill(0)
, outboxReadTill(0)
, inboxReadBefore(1)
, outboxReadBefore(1)
, showFrom(0)
, unreadBar(0)
, peer(App::peer(peerId))
@ -1321,7 +1321,7 @@ MsgId History::inboxRead(MsgId upTo) {
}
if (!upTo) upTo = msgIdForRead();
if (inboxReadTill < upTo) inboxReadTill = upTo;
inboxReadBefore = qMax(inboxReadBefore, upTo + 1);
if (!dialogs.isEmpty()) {
if (App::main()) App::main()->dlgUpdated(dialogs[0]);
@ -1339,7 +1339,7 @@ MsgId History::inboxRead(HistoryItem *wasRead) {
MsgId History::outboxRead(int32 upTo) {
if (!upTo) upTo = msgIdForRead();
if (outboxReadTill < upTo) outboxReadTill = upTo;
if (outboxReadBefore < upTo + 1) outboxReadBefore = upTo + 1;
return upTo;
}
@ -1350,10 +1350,12 @@ MsgId History::outboxRead(HistoryItem *wasRead) {
void History::setUnreadCount(int32 newUnreadCount, bool psUpdate) {
if (unreadCount != newUnreadCount) {
if (newUnreadCount == 1 && loadedAtBottom()) {
showFrom = isEmpty() ? 0 : back()->back();
if (newUnreadCount == 1) {
if (loadedAtBottom()) showFrom = isEmpty() ? 0 : back()->back();
inboxReadBefore = qMax(inboxReadBefore, msgIdForRead());
} else if (!newUnreadCount) {
showFrom = 0;
inboxReadBefore = qMax(inboxReadBefore, msgIdForRead() + 1);
}
App::histories().unreadFull += newUnreadCount - unreadCount;
if (mute) App::histories().unreadMuted += newUnreadCount - unreadCount;

View File

@ -222,7 +222,7 @@ struct History : public QList<HistoryBlock*> {
int32 geomResize(int32 newWidth, int32 *ytransform = 0, bool dontRecountText = false); // return new size
int32 width, height, msgCount, unreadCount;
int32 inboxReadTill, outboxReadTill;
int32 inboxReadBefore, outboxReadBefore;
HistoryItem *showFrom;
HistoryUnreadBar *unreadBar;
@ -705,14 +705,14 @@ public:
return _flags & MTPDmessage_flag_out;
}
bool unread() const {
if ((out() && (id > 0 && id <= _history->outboxReadTill)) || (!out() && id > 0 && id <= _history->inboxReadTill)) return false;
if ((out() && (id > 0 && id < _history->outboxReadBefore)) || (!out() && id > 0 && id < _history->inboxReadBefore)) return false;
return _flags & MTPDmessage_flag_unread;
}
bool notifyByFrom() const {
return _flags & MTPDmessage_flag_notify_by_from;
}
bool isMediaUnread() const {
return _flags & MTPDmessage_flag_media_unread;
return (_flags & MTPDmessage_flag_media_unread) && (channelId() == NoChannel); // CHANNELS_UI
}
void markMediaRead() {
_flags &= ~MTPDmessage_flag_media_unread;

View File

@ -789,7 +789,7 @@ void HistoryList::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
if (isUponSelected > 0) {
_menu->addAction(lang(lng_context_copy_selected), this, SLOT(copySelectedText()))->setEnabled(true);
}
if (item && item->id > 0 && isUponSelected != 2 && isUponSelected != -2) {
if (item && item->id > 0 && isUponSelected != 2 && isUponSelected != -2 && (!hist->peer->isChannel() || hist->peer->asChannel()->adminned)) {
_menu->addAction(lang(lng_context_reply_msg), historyWidget, SLOT(onReplyToMessage()));
}
if (lnkPhoto) {
@ -833,11 +833,11 @@ void HistoryList::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
if (isUponSelected > 0) {
if (!_menu) _menu = new ContextMenu(this);
_menu->addAction(lang(lng_context_copy_selected), this, SLOT(copySelectedText()))->setEnabled(true);
if (item && item->id > 0 && isUponSelected != 2) {
if (item && item->id > 0 && isUponSelected != 2 && (!hist->peer->isChannel() || hist->peer->asChannel()->adminned)) {
_menu->addAction(lang(lng_context_reply_msg), historyWidget, SLOT(onReplyToMessage()));
}
} else {
if (item && item->id > 0 && isUponSelected != -2) {
if (item && item->id > 0 && isUponSelected != -2 && (!hist->peer->isChannel() || hist->peer->asChannel()->adminned)) {
if (!_menu) _menu = new ContextMenu(this);
_menu->addAction(lang(lng_context_reply_msg), historyWidget, SLOT(onReplyToMessage()));
}
@ -1592,6 +1592,17 @@ void MessageField::setMaxHeight(int32 maxHeight) {
}
}
bool MessageField::hasSendText() const {
const QString &text(getLastText());
for (const QChar *ch = text.constData(), *e = ch + text.size(); ch != e; ++ch) {
ushort code = ch->unicode();
if (code != ' ' && code != '\n' && code != '\r' && !replaceCharBySpace(code)) {
return true;
}
}
return false;
}
void MessageField::onChange() {
int newh = ceil(document()->size().height()) + 2 * fakeMargin(), minh = st::btnSend.height - 2 * st::sendPadding;
if (newh > _maxHeight) {
@ -2168,8 +2179,9 @@ bool HistoryHider::offerPeer(PeerId peer) {
} else {
PeerId to = offered->id;
offered = 0;
parent()->onForward(to, _forwardSelected ? ForwardSelectedMessages : ForwardContextMessage);
startHide();
if (parent()->onForward(to, _forwardSelected ? ForwardSelectedMessages : ForwardContextMessage)) {
startHide();
}
return false;
}
@ -2381,7 +2393,7 @@ void HistoryWidget::onTextChange() {
updateSendAction(_history, SendActionTyping);
if (cHasAudioCapture()) {
if (_field.getLastText().isEmpty() && !App::main()->hasForwardingItems()) {
if (!_field.hasSendText() && !readyToForward()) {
_previewCancelled = false;
_send.hide();
setMouseTracking(true);
@ -2702,7 +2714,7 @@ void HistoryWidget::setKbWasHidden() {
_field.setMaxHeight(st::maxFieldHeight);
_kbShown = false;
_kbReplyTo = 0;
if (!App::main()->hasForwardingItems() && (!_previewData || _previewData->pendingTill < 0) && !_replyToId) {
if (!readyToForward() && (!_previewData || _previewData->pendingTill < 0) && !_replyToId) {
_replyForwardPreviewCancel.hide();
}
resizeEvent(0);
@ -2804,6 +2816,7 @@ void HistoryWidget::showPeerHistory(const PeerId &peerId, MsgId showAtMsgId) {
_peer = peerId ? App::peer(peerId) : 0;
_channel = _peer ? peerToChannel(_peer->id) : NoChannel;
_canSendMessages = canSendMessages(_peer);
_unblockRequest = 0;
@ -2862,7 +2875,7 @@ void HistoryWidget::showPeerHistory(const PeerId &peerId, MsgId showAtMsgId) {
setFieldText(_history->draft);
_field.setFocus();
_history->draftCursor.applyTo(_field, &_synthedTextUpdate);
_replyToId = App::main()->hasForwardingItems() ? 0 : _history->draftToId;
_replyToId = readyToForward() ? 0 : _history->draftToId;
if (_history->draftPreviewCancelled) {
_previewCancelled = true;
}
@ -2874,7 +2887,7 @@ void HistoryWidget::showPeerHistory(const PeerId &peerId, MsgId showAtMsgId) {
MessageCursor cur = Local::readDraftPositions(_peer->id);
cur.applyTo(_field, &_synthedTextUpdate);
}
_replyToId = App::main()->hasForwardingItems() ? 0 : draft.replyTo;
_replyToId = readyToForward() ? 0 : draft.replyTo;
if (draft.previewCancelled) {
_previewCancelled = true;
}
@ -2943,15 +2956,7 @@ void HistoryWidget::updateControlsVisibility() {
} else {
_scroll.show();
}
bool avail = false;
if (_peer->isUser()) {
avail = _peer->asUser()->access != UserNoAccess;
} else if (_peer->isChat()) {
avail = !_peer->asChat()->forbidden && !_peer->asChat()->left;
} else if (_peer->isChannel()) {
avail = !_peer->asChannel()->forbidden && !_peer->asChannel()->left && _peer->asChannel()->adminned;
}
if (avail) {
if (_canSendMessages) {
checkMentionDropdown();
if (isBlocked()) {
_botStart.hide();
@ -2990,7 +2995,7 @@ void HistoryWidget::updateControlsVisibility() {
} else {
_unblock.hide();
_botStart.hide();
if (cHasAudioCapture() && _field.getLastText().isEmpty() && !App::main()->hasForwardingItems()) {
if (cHasAudioCapture() && !_field.hasSendText() && !readyToForward()) {
_send.hide();
setMouseTracking(true);
mouseMoveEvent(0);
@ -3052,7 +3057,7 @@ void HistoryWidget::updateControlsVisibility() {
_attachPhoto.hide();
}
}
if (_replyToId || App::main()->hasForwardingItems() || (_previewData && _previewData->pendingTill >= 0) || _kbReplyTo) {
if (_replyToId || readyToForward() || (_previewData && _previewData->pendingTill >= 0) || _kbReplyTo) {
if (_replyForwardPreviewCancel.isHidden()) {
_replyForwardPreviewCancel.show();
resizeEvent(0);
@ -3069,6 +3074,10 @@ void HistoryWidget::updateControlsVisibility() {
_botStart.hide();
_attachDocument.hide();
_attachPhoto.hide();
_kbScroll.hide();
_replyForwardPreviewCancel.hide();
_attachDocument.hide();
_attachPhoto.hide();
_attachEmoji.hide();
_kbShow.hide();
_kbHide.hide();
@ -3252,8 +3261,9 @@ void HistoryWidget::firstLoadMessages() {
int32 from = 0, offset = 0, loadCount = MessagesPerPage;
if (_showAtMsgId == ShowAtUnreadMsgId) {
if (_history->unreadCount > loadCount) {
_history->getReadyFor(_showAtMsgId);
offset = _history->unreadCount - loadCount / 2;
_history->getReadyFor(_showAtMsgId)
offset = -loadCount / 2;
from = _history->inboxReadBefore;
} else {
_history->getReadyFor(ShowAtTheEndMsgId);
}
@ -3391,7 +3401,7 @@ void HistoryWidget::onSend(bool ctrlShiftEnter, MsgId replyTo) {
if (!_attachType.isHidden()) _attachType.hideStart();
if (!_emojiPan.isHidden()) _emojiPan.hideStart();
} else if (App::main()->hasForwardingItems()) {
} else if (readyToForward()) {
App::main()->readServerHistory(_history, false);
fastShowAtEnd(_history);
App::main()->finishForwarding(_history);
@ -3897,6 +3907,23 @@ void HistoryWidget::updateDragAreas() {
resizeEvent(0);
}
bool HistoryWidget::canSendMessages(PeerData *peer) {
if (peer) {
if (peer->isUser()) {
return peer->asUser()->access != UserNoAccess;
} else if (peer->isChat()) {
return !peer->asChat()->forbidden && !peer->asChat()->left;
} else if (peer->isChannel()) {
return !peer->asChannel()->forbidden && !peer->asChannel()->left && peer->asChannel()->adminned;
}
}
return false;
}
bool HistoryWidget::readyToForward() {
return _canSendMessages && !_channel && App::main()->hasForwardingItems();
}
bool HistoryWidget::isBotStart() const {
if (!_peer || !_peer->isUser() || !_peer->asUser()->botInfo) return false;
return !_peer->asUser()->botInfo->startToken.isEmpty() || (_history->isEmpty() && !_history->lastMsg);
@ -3910,7 +3937,7 @@ bool HistoryWidget::updateCmdStartShown() {
bool cmdStartShown = false;
if (_history && _peer && ((_peer->isChat() && _peer->asChat()->botStatus > 0) || (_peer->isChannel() && _peer->asChannel()->botStatus > 0) || (_peer->isUser() && _peer->asUser()->botInfo))) {
if (!isBotStart() && !isBlocked() && !_keyboard.hasMarkup() && !_keyboard.forceReply()) {
if (_field.getLastText().isEmpty()) {
if (!_field.hasSendText()) {
cmdStartShown = true;
}
}
@ -3980,7 +4007,7 @@ void HistoryWidget::onKbToggle(bool manual) {
_field.setMaxHeight(st::maxFieldHeight);
_kbReplyTo = 0;
if (!App::main()->hasForwardingItems() && (!_previewData || _previewData->pendingTill < 0) && !_replyToId) {
if (!readyToForward() && (!_previewData || _previewData->pendingTill < 0) && !_replyToId) {
_replyForwardPreviewCancel.hide();
}
} else {
@ -4689,18 +4716,10 @@ void HistoryWidget::updateListSize(int32 addToY, bool initial, bool loadedDown,
} else if (isBotStart()) {
newScrollHeight -= _botStart.height();
} else {
bool avail = false;
if (_peer->isUser()) {
avail = (_peer->asUser()->access != UserNoAccess);
} else if (_peer->isChat()) {
avail = (!_peer->asChat()->forbidden && !_peer->asChat()->left);
} else if (_peer->isChannel()) {
avail = (!_peer->asChannel()->forbidden && !_peer->asChannel()->left && _peer->asChannel()->adminned);
}
if (avail) {
if (_canSendMessages) {
newScrollHeight -= (_field.height() + 2 * st::sendPadding);
}
if (replyToId() || App::main()->hasForwardingItems() || (_previewData && _previewData->pendingTill >= 0)) {
if (replyToId() || readyToForward() || (_previewData && _previewData->pendingTill >= 0)) {
newScrollHeight -= st::replyHeight;
}
if (_kbShown) {
@ -4833,7 +4852,7 @@ void HistoryWidget::updateBotKeyboard() {
bool hasMarkup = _keyboard.hasMarkup(), forceReply = _keyboard.forceReply() && !_replyTo;
if (hasMarkup || forceReply) {
if (_keyboard.singleUse() && _keyboard.hasMarkup() && _keyboard.forMsgId() == FullMsgId(_channel, _history->lastKeyboardId) && _history->lastKeyboardUsed) _kbWasHidden = true;
if (!isBotStart() && !isBlocked() && (wasVisible || _replyTo || (_field.getLastText().isEmpty() && !_kbWasHidden))) {
if (!isBotStart() && !isBlocked() && (wasVisible || _replyTo || (!_field.hasSendText() && !_kbWasHidden))) {
if (!_showAnim.animating()) {
if (hasMarkup) {
_kbScroll.show();
@ -4867,7 +4886,7 @@ void HistoryWidget::updateBotKeyboard() {
_field.setMaxHeight(st::maxFieldHeight);
_kbShown = false;
_kbReplyTo = 0;
if (!App::main()->hasForwardingItems() && (!_previewData || _previewData->pendingTill < 0) && !_replyToId) {
if (!readyToForward() && (!_previewData || _previewData->pendingTill < 0) && !_replyToId) {
_replyForwardPreviewCancel.hide();
}
}
@ -4882,7 +4901,7 @@ void HistoryWidget::updateBotKeyboard() {
_field.setMaxHeight(st::maxFieldHeight);
_kbShown = false;
_kbReplyTo = 0;
if (!App::main()->hasForwardingItems() && (!_previewData || _previewData->pendingTill < 0) && !_replyToId) {
if (!readyToForward() && (!_previewData || _previewData->pendingTill < 0) && !_replyToId) {
_replyForwardPreviewCancel.hide();
}
}
@ -5046,7 +5065,7 @@ void HistoryWidget::setFieldText(const QString &text) {
void HistoryWidget::onReplyToMessage() {
HistoryItem *to = App::contextItem();
if (!to || to->id <= 0) return;
if (!to || to->id <= 0 || (_peer->isChannel() && !_peer->asChannel()->adminned)) return;
App::main()->cancelForwarding();
@ -5078,7 +5097,7 @@ void HistoryWidget::cancelReply(bool lastKeyboardUsed) {
_replyTo = 0;
_replyToId = 0;
mouseMoveEvent(0);
if (!App::main()->hasForwardingItems() && (!_previewData || _previewData->pendingTill < 0) && !_kbReplyTo) {
if (!readyToForward() && (!_previewData || _previewData->pendingTill < 0) && !_kbReplyTo) {
_replyForwardPreviewCancel.hide();
}
@ -5113,7 +5132,7 @@ void HistoryWidget::onReplyForwardPreviewCancel() {
_saveDraftText = true;
_saveDraftStart = getms();
onDraftSave();
} else if (App::main()->hasForwardingItems()) {
} else if (readyToForward()) {
App::main()->cancelForwarding();
} else if (_replyToId) {
cancelReply();
@ -5138,7 +5157,7 @@ void HistoryWidget::previewCancel() {
_previewData = 0;
_previewLinks.clear();
updatePreview();
if (!_replyToId && !App::main()->hasForwardingItems() && !_kbReplyTo) _replyForwardPreviewCancel.hide();
if (!_replyToId && !readyToForward() && !_kbReplyTo) _replyForwardPreviewCancel.hide();
}
void HistoryWidget::onPreviewParse() {
@ -5239,7 +5258,7 @@ void HistoryWidget::updatePreview() {
_previewTitle.setText(st::msgServiceNameFont, title, _textNameOptions);
_previewDescription.setText(st::msgFont, desc, _textDlgOptions);
}
} else if (!App::main()->hasForwardingItems() && !replyToId()) {
} else if (!readyToForward() && !replyToId()) {
_replyForwardPreviewCancel.hide();
}
resizeEvent(0);
@ -5254,6 +5273,14 @@ void HistoryWidget::onCancel() {
void HistoryWidget::onFullPeerUpdated(PeerData *data) {
int32 newScrollTop = _scroll.scrollTop();
if (_list && data == _peer) {
bool newCanSendMessages = canSendMessages(_peer);
if (newCanSendMessages != _canSendMessages) {
_canSendMessages = newCanSendMessages;
if (!_canSendMessages) {
cancelReply();
}
updateControlsVisibility();
}
checkMentionDropdown();
int32 lh = _list->height(), st = _scroll.scrollTop();
_list->updateBotInfo();
@ -5322,7 +5349,7 @@ void HistoryWidget::onDeleteSelectedSure() {
}
if (!ids.isEmpty()) {
App::main()->deleteMessages(ids);
App::main()->deleteMessages(_peer, ids);
}
onClearSelected();
@ -5342,7 +5369,7 @@ void HistoryWidget::onDeleteContextSure() {
}
if (item->id > 0) {
App::main()->deleteMessages(QVector<MTPint>(1, MTP_int(item->id)));
App::main()->deleteMessages(item->history()->peer, QVector<MTPint>(1, MTP_int(item->id)));
}
item->destroy();
if (App::main() && App::main()->peer() == peer()) {
@ -5429,7 +5456,7 @@ void HistoryWidget::updateReplyTo(bool force) {
}
void HistoryWidget::updateForwarding(bool force) {
if (App::main()->hasForwardingItems()) {
if (readyToForward()) {
updateControlsVisibility();
} else {
resizeEvent(0);
@ -5451,7 +5478,7 @@ void HistoryWidget::updateField() {
void HistoryWidget::drawField(Painter &p) {
int32 backy = _field.y() - st::sendPadding, backh = _field.height() + 2 * st::sendPadding;
Text *from = 0, *text = 0;
bool serviceColor = false, hasForward = App::main()->hasForwardingItems();
bool serviceColor = false, hasForward = readyToForward();
ImagePtr preview;
HistoryItem *drawReplyTo = _replyToId ? _replyTo : _kbReplyTo;
if (_replyToId || (!hasForward && _kbReplyTo)) {

View File

@ -192,6 +192,18 @@ public:
void focusInEvent(QFocusEvent *e);
void setMaxHeight(int32 maxHeight);
bool hasSendText() const;
static bool replaceCharBySpace(ushort code) {
// \xe2\x80[\xa8 - \xac\xad] // 8232 - 8237
// QString from1 = QString::fromUtf8("\xe2\x80\xa8"), to1 = QString::fromUtf8("\xe2\x80\xad");
// \xcc[\xb3\xbf\x8a] // 819, 831, 778
// QString bad1 = QString::fromUtf8("\xcc\xb3"), bad2 = QString::fromUtf8("\xcc\xbf"), bad3 = QString::fromUtf8("\xcc\x8a");
// [\x00\x01\x02\x07\x08\x0b-\x1f] // '\t' = 0x09
return (code >= 0x00 && code <= 0x02) || (code >= 0x07 && code <= 0x09) || (code >= 0x0b && code <= 0x1f) ||
(code == 819) || (code == 831) || (code == 778) || (code >= 8232 && code <= 8237);
}
public slots:
void onChange();
@ -624,8 +636,12 @@ private:
void updateDragAreas();
bool canSendMessages(PeerData *peer);
bool readyToForward();
PeerData *_peer;
ChannelId _channel;
bool _canSendMessages;
MsgId _showAtMsgId;
mtpRequestId _firstLoadRequest, _preloadRequest, _preloadDownRequest;

View File

@ -431,7 +431,12 @@ _failDifferenceTimeout(1), _lastUpdateTime(0), _cachedX(0), _cachedY(0), _backgr
_api->init();
}
void MainWidget::onForward(const PeerId &peer, ForwardWhatMessages what) {
bool MainWidget::onForward(const PeerId &peer, ForwardWhatMessages what) {
PeerData *p = App::peer(peer);
if (!peer || p->isChannel() || (p->isChat() && p->asChat()->forbidden) || (p->isUser() && p->asUser()->access == UserNoAccess)) {
App::wnd()->showLayer(new ConfirmBox(lang(lng_forward_cant), true));
return false;
}
history.cancelReply();
_toForward.clear();
if (what == ForwardSelectedMessages) {
@ -457,6 +462,7 @@ void MainWidget::onForward(const PeerId &peer, ForwardWhatMessages what) {
showPeerHistory(peer, ShowAtUnreadMsgId);
history.onClearSelected();
history.updateForwarding();
return true;
}
bool MainWidget::hasForwardingItems() {
@ -780,8 +786,12 @@ void MainWidget::deleteHistoryPart(PeerData *peer, const MTPmessages_AffectedHis
MTP::send(MTPmessages_DeleteHistory(peer->input, d.voffset), rpcDone(&MainWidget::deleteHistoryPart, peer));
}
void MainWidget::deleteMessages(const QVector<MTPint> &ids) {
MTP::send(MTPmessages_DeleteMessages(MTP_vector<MTPint>(ids)), rpcDone(&MainWidget::messagesAffected));
void MainWidget::deleteMessages(PeerData *peer, const QVector<MTPint> &ids) {
if (peer->isChannel()) {
MTP::send(MTPmessages_DeleteChannelMessages(peer->asChannel()->input, MTP_vector<MTPint>(ids)), rpcDone(&MainWidget::messagesAffected, peer));
} else {
MTP::send(MTPmessages_DeleteMessages(MTP_vector<MTPint>(ids)), rpcDone(&MainWidget::messagesAffected, peer));
}
}
void MainWidget::deletedContact(UserData *user, const MTPcontacts_Link &result) {
@ -1012,16 +1022,6 @@ DialogsIndexed &MainWidget::dialogsList() {
return dialogs.dialogsList();
}
inline bool replaceCharBySpace(ushort code) {
// \xe2\x80[\xa8 - \xac\xad] // 8232 - 8237
// QString from1 = QString::fromUtf8("\xe2\x80\xa8"), to1 = QString::fromUtf8("\xe2\x80\xad");
// \xcc[\xb3\xbf\x8a] // 819, 831, 778
// QString bad1 = QString::fromUtf8("\xcc\xb3"), bad2 = QString::fromUtf8("\xcc\xbf"), bad3 = QString::fromUtf8("\xcc\x8a");
// [\x00\x01\x02\x07\x08\x0b-\x1f] // '\t' = 0x09
return (code >= 0x00 && code <= 0x02) || (code >= 0x07 && code <= 0x09) || (code >= 0x0b && code <= 0x1f) ||
(code == 819) || (code == 831) || (code == 778) || (code >= 8232 && code <= 8237);
}
QString cleanMessage(const QString &text) {
QString result = text;
QChar *_start = result.data(), *_end = _start + result.size(), *start = _start, *end = _end, *ch = start, *copy = 0;
@ -1029,7 +1029,7 @@ QString cleanMessage(const QString &text) {
if (ch->unicode() == '\r') {
copy = ch + 1;
break;
} else if (replaceCharBySpace(ch->unicode())) {
} else if (MessageField::replaceCharBySpace(ch->unicode())) {
*ch = ' ';
}
}
@ -1037,7 +1037,7 @@ QString cleanMessage(const QString &text) {
for (; copy != end; ++copy) {
if (copy->unicode() == '\r') {
continue;
} else if (replaceCharBySpace(copy->unicode())) {
} else if (MessageField::replaceCharBySpace(copy->unicode())) {
*ch++ = ' ';
} else {
*ch++ = *copy;
@ -1512,9 +1512,13 @@ void MainWidget::readRequestDone(PeerData *peer) {
}
}
void MainWidget::messagesAffected(const MTPmessages_AffectedMessages &result) {
void MainWidget::messagesAffected(PeerData *peer, const MTPmessages_AffectedMessages &result) {
const MTPDmessages_affectedMessages &d(result.c_messages_affectedMessages());
updPtsUpdated(d.vpts.v, d.vpts_count.v);
if (peer && peer->isChannel()) {
// CHANNELS_TODO
} else {
updPtsUpdated(d.vpts.v, d.vpts_count.v);
}
}
void MainWidget::videoLoadProgress(mtpFileLoader *loader) {
@ -1840,7 +1844,7 @@ void MainWidget::mediaMarkRead(const HistoryItemsMap &items) {
}
}
if (!markedIds.isEmpty()) {
MTP::send(MTPmessages_ReadMessageContents(MTP_vector<MTPint>(markedIds)), rpcDone(&MainWidget::messagesAffected));
MTP::send(MTPmessages_ReadMessageContents(MTP_vector<MTPint>(markedIds)), rpcDone(&MainWidget::messagesAffected, (PeerData*)0));
}
}

View File

@ -272,7 +272,7 @@ public:
void shareContactLayer(UserData *contact);
void hiderLayer(HistoryHider *h);
void noHider(HistoryHider *destroyed);
void onForward(const PeerId &peer, ForwardWhatMessages what);
bool onForward(const PeerId &peer, ForwardWhatMessages what);
void onShareContact(const PeerId &peer, UserData *contact);
void onSendPaths(const PeerId &peer);
void onFilesOrForwardDrop(const PeerId &peer, const QMimeData *data);
@ -285,7 +285,7 @@ public:
bool leaveChatFailed(PeerData *peer, const RPCError &e);
void deleteHistoryAfterLeave(PeerData *peer, const MTPUpdates &updates);
void deleteHistoryPart(PeerData *peer, const MTPmessages_AffectedHistory &result);
void deleteMessages(const QVector<MTPint> &ids);
void deleteMessages(PeerData *peer, const QVector<MTPint> &ids);
void deletedContact(UserData *user, const MTPcontacts_Link &result);
void deleteConversation(PeerData *peer);
void clearHistory(PeerData *peer);
@ -453,7 +453,7 @@ private:
bool readRequestFail(PeerData *peer, const RPCError &error);
void readRequestDone(PeerData *peer);
void messagesAffected(const MTPmessages_AffectedMessages &result);
void messagesAffected(PeerData *peer, const MTPmessages_AffectedMessages &result);
void photosLoaded(History *h, const MTPmessages_Messages &msgs, mtpRequestId req);
bool _started;

View File

@ -64,7 +64,7 @@ _docRadialFirst(0), _docRadialStart(0), _docRadialLast(0), _docRadialOpacity(1),
_docDownload(this, lang(lng_media_download), st::mvDocLink),
_docSaveAs(this, lang(lng_mediaview_save_as), st::mvDocLink),
_docCancel(this, lang(lng_cancel), st::mvDocLink),
_history(0), _peer(0), _user(0), _from(0), _index(-1), _msgid(0), _channel(NoChannel),
_history(0), _peer(0), _user(0), _from(0), _index(-1), _msgid(0), _channel(NoChannel), _canForward(false), _canDelete(false),
_loadRequest(0), _over(OverNone), _down(OverNone), _lastAction(-st::mvDeltaFromLastAction, -st::mvDeltaFromLastAction), _ignoringDropdown(false),
_controlsState(ControlsShown), _controlsAnimStarted(0),
_menu(0), _dropdown(this, st::mvDropdown), _receiveMouse(true), _touchPress(false), _touchMove(false), _touchRightButton(false),
@ -314,8 +314,8 @@ void MediaView::updateDropdown() {
_btnShowInFolder->setVisible(_doc && !_doc->already(true).isEmpty());
_btnSaveAs->setVisible(true);
_btnCopy->setVisible((_doc && !_current.isNull()) || (_photo && _photo->full->loaded()));
_btnForward->setVisible(_msgid > 0 && !_channel);
_btnDelete->setVisible(_msgid > 0 || (_photo && App::self() && App::self()->photoId == _photo->id) || (_photo && _photo->peer && _photo->peer->photoId == _photo->id));
_btnForward->setVisible(_canForward);
_btnDelete->setVisible(_canDelete || (_photo && App::self() && App::self()->photoId == _photo->id) || (_photo && _photo->peer && _photo->peer->photoId == _photo->id));
_btnViewAll->setVisible((_overview != OverviewCount) && _history);
_btnViewAll->setText(lang(_doc ? lng_mediaview_files_all : lng_mediaview_photos_all));
_dropdown.updateButtons();
@ -655,6 +655,8 @@ void MediaView::showPhoto(PhotoData *photo, HistoryItem *context) {
_index = -1;
_msgid = context ? context->id : 0;
_channel = context ? context->channelId() : NoChannel;
_canForward = _msgid > 0 && (_channel == NoChannel);
_canDelete = (_channel == NoChannel) || context->history()->peer->asChannel()->adminned;
_photo = photo;
if (_history) {
_overview = OverviewPhotos;
@ -682,6 +684,7 @@ void MediaView::showPhoto(PhotoData *photo, PeerData *context) {
_msgid = 0;
_channel = NoChannel;
_canForward = _canDelete = false;
_index = -1;
_photo = photo;
_overview = OverviewCount;
@ -725,6 +728,8 @@ void MediaView::showDocument(DocumentData *doc, HistoryItem *context) {
_index = -1;
_msgid = context ? context->id : 0;
_channel = context ? context->channelId() : NoChannel;
_canForward = _msgid > 0 && (_channel == NoChannel);
_canDelete = (_channel == NoChannel) || context->history()->peer->asChannel()->adminned;
if (_history) {
_overview = OverviewDocuments;
@ -1385,6 +1390,8 @@ void MediaView::moveToNext(int32 delta) {
if (HistoryItem *item = App::histItemById(_history->channelId(), _history->_overview[_overview][_index])) {
_msgid = item->id;
_channel = item->channelId();
_canForward = _msgid > 0 && (_channel == NoChannel);
_canDelete = (_channel == NoChannel) || item->history()->peer->asChannel()->adminned;
if (item->getMedia()) {
switch (item->getMedia()->type()) {
case MediaTypePhoto: displayPhoto(static_cast<HistoryPhoto*>(item->getMedia())->photo(), item); preloadData(delta); break;

View File

@ -161,6 +161,7 @@ private:
int32 _index; // index in photos or files array, -1 if just photo
MsgId _msgid; // msgId of current photo or file
ChannelId _channel;
bool _canForward, _canDelete;
mtpRequestId _loadRequest;

View File

@ -856,6 +856,10 @@ void OverviewInner::touchScrollUpdated(const QPoint &screenPos) {
void OverviewInner::applyDragSelection() {
if (_dragSelFromIndex < 0 || _dragSelToIndex < 0) return;
if (_peer && _peer->isChannel() && !_peer->asChannel()->adminned) {
_selected.clear();
return;
}
if (!_selected.isEmpty() && _selected.cbegin().value() != FullItemSel) {
_selected.clear();
}
@ -1781,12 +1785,16 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
_menu->addAction(lang(lng_context_clear_selection), _overview, SLOT(onClearSelected()));
} else if (App::hoveredLinkItem()) {
if (isUponSelected != -2) {
if (dynamic_cast<HistoryMessage*>(App::hoveredLinkItem()) && !_hist->peer->isChannel()) {
if (App::hoveredLinkItem()->toHistoryMessage() && !_peer->isChannel()) {
_menu->addAction(lang(lng_context_forward_msg), this, SLOT(forwardMessage()))->setEnabled(true);
}
_menu->addAction(lang(lng_context_delete_msg), this, SLOT(deleteMessage()))->setEnabled(true);
if (!_peer->isChannel() || _peer->asChannel()->adminned) {
_menu->addAction(lang(lng_context_delete_msg), this, SLOT(deleteMessage()))->setEnabled(true);
}
}
if (App::hoveredLinkItem()->id > 0 && (!_peer->isChannel() || _peer->asChannel()->adminned)) {
_menu->addAction(lang(lng_context_select_msg), this, SLOT(selectMessage()))->setEnabled(true);
}
_menu->addAction(lang(lng_context_select_msg), this, SLOT(selectMessage()))->setEnabled(true);
}
App::contextItem(App::hoveredLinkItem());
updateMsg(App::contextItem());
@ -1815,12 +1823,16 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
_menu->addAction(lang(lng_context_clear_selection), _overview, SLOT(onClearSelected()));
} else {
if (isUponSelected != -2) {
if (dynamic_cast<HistoryMessage*>(App::mousedItem()) && !_hist->peer->isChannel()) {
if (App::mousedItem()->toHistoryMessage() && !_peer->isChannel()) {
_menu->addAction(lang(lng_context_forward_msg), this, SLOT(forwardMessage()))->setEnabled(true);
}
_menu->addAction(lang(lng_context_delete_msg), this, SLOT(deleteMessage()))->setEnabled(true);
if (!_peer->isChannel() || _peer->asChannel()->adminned) {
_menu->addAction(lang(lng_context_delete_msg), this, SLOT(deleteMessage()))->setEnabled(true);
}
}
if (App::mousedItem()->id > 0 && (!_peer->isChannel() || _peer->asChannel()->adminned)) {
_menu->addAction(lang(lng_context_select_msg), this, SLOT(selectMessage()))->setEnabled(true);
}
_menu->addAction(lang(lng_context_select_msg), this, SLOT(selectMessage()))->setEnabled(true);
}
App::contextItem(App::mousedItem());
updateMsg(App::contextItem());
@ -1931,7 +1943,7 @@ void OverviewInner::deleteMessage() {
HistoryItem *item = App::contextItem();
if (!item || item->itemType() != HistoryItem::MsgType) return;
HistoryMessage *msg = dynamic_cast<HistoryMessage*>(item);
HistoryMessage *msg = item->toHistoryMessage();
App::main()->deleteLayer((msg && msg->uploading()) ? -2 : -1);
}
@ -2098,7 +2110,7 @@ void OverviewInner::fillSelectedItems(SelectedItemSet &sel, bool forDelete) {
for (SelectedItems::const_iterator i = _selected.cbegin(), e = _selected.cend(); i != e; ++i) {
HistoryItem *item = App::histItemById(_channel, i.key());
if (dynamic_cast<HistoryMessage*>(item) && item->id > 0) {
if (item && item->toHistoryMessage() && item->id > 0) {
sel.insert(item->id, item);
}
}
@ -2924,7 +2936,7 @@ void OverviewWidget::onDeleteSelectedSure() {
}
if (!ids.isEmpty()) {
App::main()->deleteMessages(ids);
App::main()->deleteMessages(peer(), ids);
}
onClearSelected();
@ -2944,7 +2956,7 @@ void OverviewWidget::onDeleteContextSure() {
}
if (item->id > 0) {
App::main()->deleteMessages(QVector<MTPint>(1, MTP_int(item->id)));
App::main()->deleteMessages(item->history()->peer, QVector<MTPint>(1, MTP_int(item->id)));
}
item->destroy();
if (App::main() && App::main()->peer() == peer()) {

View File

@ -245,7 +245,7 @@ namespace {
Gdiplus::Status gdiRes = Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
if (gdiRes != Gdiplus::Ok) {
DEBUG_LOG(("Application Error: could not init GDI+, error: %1").arg((int)gdiRes));
LOG(("Application Error: could not init GDI+, error: %1").arg((int)gdiRes));
return false;
}
blend.AlphaFormat = AC_SRC_ALPHA;
@ -254,7 +254,10 @@ namespace {
blend.BlendOp = AC_SRC_OVER;
screenDC = GetDC(0);
if (!screenDC) return false;
if (!screenDC) {
LOG(("Application Error: could not GetDC(0), error: %2").arg(GetLastError()));
return false;
}
QRect avail(App::app() ? App::app()->desktop()->availableGeometry() : QDesktopWidget().availableGeometry());
max_w = avail.width();
@ -283,14 +286,14 @@ namespace {
wc.lpszClassName = _cn;
wc.hIconSm = 0;
if (!RegisterClassEx(&wc)) {
DEBUG_LOG(("Application Error: could not register shadow window class %1, error: %2").arg(i).arg(GetLastError()));
LOG(("Application Error: could not register shadow window class %1, error: %2").arg(i).arg(GetLastError()));
destroy();
return false;
}
hwnds[i] = CreateWindowEx(WS_EX_LAYERED | WS_EX_TOOLWINDOW, _cn, 0, WS_POPUP, 0, 0, 0, 0, 0, 0, appinst, 0);
if (!hwnds[i]) {
DEBUG_LOG(("Application Error: could not create shadow window class %1, error: %2").arg(i).arg(GetLastError()));
LOG(("Application Error: could not create shadow window class %1, error: %2").arg(i).arg(GetLastError()));
destroy();
return false;
}
@ -298,14 +301,14 @@ namespace {
dcs[i] = CreateCompatibleDC(screenDC);
if (!dcs[i]) {
DEBUG_LOG(("Application Error: could not create dc for shadow window class %1, error: %2").arg(i).arg(GetLastError()));
LOG(("Application Error: could not create dc for shadow window class %1, error: %2").arg(i).arg(GetLastError()));
destroy();
return false;
}
bitmaps[i] = CreateCompatibleBitmap(screenDC, (i % 2) ? _size : max_w, (i % 2) ? max_h : _size);
if (!bitmaps[i]) {
DEBUG_LOG(("Application Error: could not create bitmap for shadow window class %1, error: %2").arg(i).arg(GetLastError()));
LOG(("Application Error: could not create bitmap for shadow window class %1, error: %2").arg(i).arg(GetLastError()));
destroy();
return false;
}