Using square rounded photos in native notifications (Win, OS X).

When updating local online status from user action events we use
action timestamp, and ignoring events from getDifference, if no
timestamp is available for the specific action.
Couple of hidden actions added in Settings. Alpha version 0.9.54.
This commit is contained in:
John Preston 2016-06-22 21:41:13 +03:00
parent 701b8c87e6
commit cbde6e1ee9
26 changed files with 159 additions and 55 deletions

View File

@ -34,8 +34,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,9,53,0 FILEVERSION 0,9,54,0
PRODUCTVERSION 0,9,53,0 PRODUCTVERSION 0,9,54,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -51,10 +51,10 @@ BEGIN
BLOCK "040904b0" BLOCK "040904b0"
BEGIN BEGIN
VALUE "CompanyName", "Telegram Messenger LLP" VALUE "CompanyName", "Telegram Messenger LLP"
VALUE "FileVersion", "0.9.53.0" VALUE "FileVersion", "0.9.54.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2016" VALUE "LegalCopyright", "Copyright (C) 2014-2016"
VALUE "ProductName", "Telegram Desktop" VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "0.9.53.0" VALUE "ProductVersion", "0.9.54.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View File

@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,9,53,0 FILEVERSION 0,9,54,0
PRODUCTVERSION 0,9,53,0 PRODUCTVERSION 0,9,54,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -43,10 +43,10 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "Telegram Messenger LLP" VALUE "CompanyName", "Telegram Messenger LLP"
VALUE "FileDescription", "Telegram Updater" VALUE "FileDescription", "Telegram Updater"
VALUE "FileVersion", "0.9.53.0" VALUE "FileVersion", "0.9.54.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2016" VALUE "LegalCopyright", "Copyright (C) 2014-2016"
VALUE "ProductName", "Telegram Desktop" VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "0.9.53.0" VALUE "ProductVersion", "0.9.54.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View File

@ -1223,7 +1223,7 @@ namespace {
} }
} }
void feedOutboxRead(const PeerId &peer, MsgId upTo) { void feedOutboxRead(const PeerId &peer, MsgId upTo, TimeId when) {
if (auto history = App::historyLoaded(peer)) { if (auto history = App::historyLoaded(peer)) {
history->outboxRead(upTo); history->outboxRead(upTo);
if (history->lastMsg && history->lastMsg->out() && history->lastMsg->id <= upTo) { if (history->lastMsg && history->lastMsg->out() && history->lastMsg->id <= upTo) {
@ -1232,7 +1232,7 @@ namespace {
history->updateChatListEntry(); history->updateChatListEntry();
if (history->peer->isUser()) { if (history->peer->isUser()) {
history->peer->asUser()->madeAction(); history->peer->asUser()->madeAction(when);
} }
} }
} }

View File

@ -83,7 +83,7 @@ namespace App {
void feedMsgs(const QVector<MTPMessage> &msgs, NewMessageType type); void feedMsgs(const QVector<MTPMessage> &msgs, NewMessageType type);
void feedMsgs(const MTPVector<MTPMessage> &msgs, NewMessageType type); void feedMsgs(const MTPVector<MTPMessage> &msgs, NewMessageType type);
void feedInboxRead(const PeerId &peer, MsgId upTo); void feedInboxRead(const PeerId &peer, MsgId upTo);
void feedOutboxRead(const PeerId &peer, MsgId upTo); void feedOutboxRead(const PeerId &peer, MsgId upTo, TimeId when);
void feedWereDeleted(ChannelId channelId, const QVector<MTPint> &msgsIds); void feedWereDeleted(ChannelId channelId, const QVector<MTPint> &msgsIds);
void feedUserLink(MTPint userId, const MTPContactLink &myLink, const MTPContactLink &foreignLink); void feedUserLink(MTPint userId, const MTPContactLink &myLink, const MTPContactLink &foreignLink);

View File

@ -1049,8 +1049,8 @@ void AppClass::checkMapVersion() {
if (Local::oldMapVersion() < AppVersion) { if (Local::oldMapVersion() < AppVersion) {
if (Local::oldMapVersion()) { if (Local::oldMapVersion()) {
QString versionFeatures; QString versionFeatures;
if ((cAlphaVersion() || cBetaVersion()) && Local::oldMapVersion() < 9053) { if ((cAlphaVersion() || cBetaVersion()) && Local::oldMapVersion() < 9054) {
versionFeatures = QString::fromUtf8("\xe2\x80\x94 Put your cursor over the members count in a group chat to see the members list\n\xe2\x80\x94 Bug fixes and other minor improvements"); versionFeatures = QString::fromUtf8("\xe2\x80\x94 Photo viewer handles screen resolution change\n\xe2\x80\x94 Forward photo by drag-n-drop fixed\n\xe2\x80\x94 Some design improvements and bug fixes");
// versionFeatures = langNewVersionText(); // versionFeatures = langNewVersionText();
} else if (Local::oldMapVersion() < 9050) { } else if (Local::oldMapVersion() < 9050) {
versionFeatures = langNewVersionText(); versionFeatures = langNewVersionText();

View File

@ -130,9 +130,9 @@ TimeId fromServerTime(const MTPint &serverTime) {
return serverTime.v - unixtimeDelta; return serverTime.v - unixtimeDelta;
} }
MTPint toServerTime(const TimeId &clientTime) { void toServerTime(const TimeId &clientTime, MTPint &outServerTime) {
QReadLocker locker(&unixtimeLock); QReadLocker locker(&unixtimeLock);
return MTP_int(clientTime + unixtimeDelta); outServerTime = MTP_int(clientTime + unixtimeDelta);
} }
QDateTime dateFromServerTime(TimeId time) { QDateTime dateFromServerTime(TimeId time) {

View File

@ -490,6 +490,7 @@ void unixtimeInit();
void unixtimeSet(TimeId servertime, bool force = false); void unixtimeSet(TimeId servertime, bool force = false);
TimeId unixtime(); TimeId unixtime();
TimeId fromServerTime(const MTPint &serverTime); TimeId fromServerTime(const MTPint &serverTime);
void toServerTime(const TimeId &clientTime, MTPint &outServerTime);
uint64 msgid(); uint64 msgid();
int32 reqid(); int32 reqid();

View File

@ -24,7 +24,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#define BETA_VERSION_MACRO (0ULL) #define BETA_VERSION_MACRO (0ULL)
constexpr int AppVersion = 9053; constexpr int AppVersion = 9054;
constexpr str_const AppVersionStr = "0.9.53"; constexpr str_const AppVersionStr = "0.9.54";
constexpr bool AppAlphaVersion = true; constexpr bool AppAlphaVersion = true;
constexpr uint64 AppBetaVersion = BETA_VERSION_MACRO; constexpr uint64 AppBetaVersion = BETA_VERSION_MACRO;

View File

@ -532,6 +532,7 @@ struct Data {
bool AdaptiveForWide = true; bool AdaptiveForWide = true;
bool DialogsModeEnabled = false; bool DialogsModeEnabled = false;
Dialogs::Mode DialogsMode = Dialogs::Mode::All; Dialogs::Mode DialogsMode = Dialogs::Mode::All;
bool ModerateModeEnabled = false;
int32 DebugLoggingFlags = 0; int32 DebugLoggingFlags = 0;
@ -597,6 +598,7 @@ DefineVar(Global, Adaptive::Layout, AdaptiveLayout);
DefineVar(Global, bool, AdaptiveForWide); DefineVar(Global, bool, AdaptiveForWide);
DefineVar(Global, bool, DialogsModeEnabled); DefineVar(Global, bool, DialogsModeEnabled);
DefineVar(Global, Dialogs::Mode, DialogsMode); DefineVar(Global, Dialogs::Mode, DialogsMode);
DefineVar(Global, bool, ModerateModeEnabled);
DefineVar(Global, int32, DebugLoggingFlags); DefineVar(Global, int32, DebugLoggingFlags);

View File

@ -211,6 +211,7 @@ DeclareVar(Adaptive::Layout, AdaptiveLayout);
DeclareVar(bool, AdaptiveForWide); DeclareVar(bool, AdaptiveForWide);
DeclareVar(bool, DialogsModeEnabled); DeclareVar(bool, DialogsModeEnabled);
DeclareVar(Dialogs::Mode, DialogsMode); DeclareVar(Dialogs::Mode, DialogsMode);
DeclareVar(bool, ModerateModeEnabled);
DeclareVar(int32, DebugLoggingFlags); DeclareVar(int32, DebugLoggingFlags);

View File

@ -604,7 +604,7 @@ void Histories::clear() {
typing.clear(); typing.clear();
} }
void Histories::regSendAction(History *history, UserData *user, const MTPSendMessageAction &action) { void Histories::regSendAction(History *history, UserData *user, const MTPSendMessageAction &action, TimeId when) {
if (action.type() == mtpc_sendMessageCancelAction) { if (action.type() == mtpc_sendMessageCancelAction) {
history->unregTyping(user); history->unregTyping(user);
return; return;
@ -624,7 +624,7 @@ void Histories::regSendAction(History *history, UserData *user, const MTPSendMes
default: return; default: return;
} }
user->madeAction(); user->madeAction(when);
TypingHistories::const_iterator i = typing.find(history); TypingHistories::const_iterator i = typing.find(history);
if (i == typing.cend()) { if (i == typing.cend()) {
@ -1140,7 +1140,9 @@ void History::newItemAdded(HistoryItem *item) {
if (item->from() == item->author()) { if (item->from() == item->author()) {
unregTyping(item->from()->asUser()); unregTyping(item->from()->asUser());
} }
item->from()->asUser()->madeAction(); MTPint itemServerTime;
toServerTime(item->date.toTime_t(), itemServerTime);
item->from()->asUser()->madeAction(itemServerTime.v);
} }
if (item->out()) { if (item->out()) {
if (unreadBar) unreadBar->destroyUnreadBar(); if (unreadBar) unreadBar->destroyUnreadBar();

View File

@ -44,7 +44,7 @@ public:
Histories() : _a_typings(animation(this, &Histories::step_typings)), _unreadFull(0), _unreadMuted(0) { Histories() : _a_typings(animation(this, &Histories::step_typings)), _unreadFull(0), _unreadMuted(0) {
} }
void regSendAction(History *history, UserData *user, const MTPSendMessageAction &action); void regSendAction(History *history, UserData *user, const MTPSendMessageAction &action, TimeId when);
void step_typings(uint64 ms, bool timer); void step_typings(uint64 ms, bool timer);
History *find(const PeerId &peerId); History *find(const PeerId &peerId);

View File

@ -493,14 +493,24 @@ bool FieldAutocomplete::chooseSelected(ChooseMethod method) const {
} }
bool FieldAutocomplete::eventFilter(QObject *obj, QEvent *e) { bool FieldAutocomplete::eventFilter(QObject *obj, QEvent *e) {
if (isHidden()) return QWidget::eventFilter(obj, e); auto hidden = isHidden();
auto moderate = Global::ModerateModeEnabled();
if (hidden && !moderate) return QWidget::eventFilter(obj, e);
if (e->type() == QEvent::KeyPress) { if (e->type() == QEvent::KeyPress) {
QKeyEvent *ev = static_cast<QKeyEvent*>(e); QKeyEvent *ev = static_cast<QKeyEvent*>(e);
if (!(ev->modifiers() & (Qt::AltModifier | Qt::ControlModifier | Qt::ShiftModifier | Qt::MetaModifier))) { if (!(ev->modifiers() & (Qt::AltModifier | Qt::ControlModifier | Qt::ShiftModifier | Qt::MetaModifier))) {
if (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down || (!_srows.isEmpty() && (ev->key() == Qt::Key_Left || ev->key() == Qt::Key_Right))) { if (!hidden) {
return _inner->moveSel(ev->key()); if (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down || (!_srows.isEmpty() && (ev->key() == Qt::Key_Left || ev->key() == Qt::Key_Right))) {
} else if (ev->key() == Qt::Key_Enter || ev->key() == Qt::Key_Return) { return _inner->moveSel(ev->key());
return _inner->chooseSelected(ChooseMethod::ByEnter); } else if (ev->key() == Qt::Key_Enter || ev->key() == Qt::Key_Return) {
return _inner->chooseSelected(ChooseMethod::ByEnter);
}
}
if (moderate && ev->key() >= Qt::Key_1 && ev->key() <= Qt::Key_9) {
bool handled = false;
emit moderateKeyActivate(ev->key() - Qt::Key_1, &handled);
return handled;
} }
} }
} }

View File

@ -85,6 +85,8 @@ signals:
void botCommandChosen(QString command, FieldAutocomplete::ChooseMethod method) const; void botCommandChosen(QString command, FieldAutocomplete::ChooseMethod method) const;
void stickerChosen(DocumentData *sticker, FieldAutocomplete::ChooseMethod method) const; void stickerChosen(DocumentData *sticker, FieldAutocomplete::ChooseMethod method) const;
void moderateKeyActivate(int index, bool *outHandled) const;
public slots: public slots:
void hideStart(); void hideStart();

View File

@ -2481,6 +2481,18 @@ void BotKeyboard::leaveEvent(QEvent *e) {
clearSelection(); clearSelection();
} }
bool BotKeyboard::moderateKeyActivate(int index) {
if (auto item = App::histItemById(_wasForMsgId)) {
if (auto markup = item->Get<HistoryMessageReplyMarkup>()) {
if (!markup->rows.isEmpty() && index >= 0 && index < markup->rows.front().size()) {
App::activateBotCommand(item, 0, index);
return true;
}
}
}
return false;
}
void BotKeyboard::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) { void BotKeyboard::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) {
if (!_impl) return; if (!_impl) return;
_impl->clickHandlerActiveChanged(p, active); _impl->clickHandlerActiveChanged(p, active);
@ -3086,6 +3098,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
connect(_fieldAutocomplete, SIGNAL(hashtagChosen(QString,FieldAutocomplete::ChooseMethod)), this, SLOT(onHashtagOrBotCommandInsert(QString,FieldAutocomplete::ChooseMethod))); connect(_fieldAutocomplete, SIGNAL(hashtagChosen(QString,FieldAutocomplete::ChooseMethod)), this, SLOT(onHashtagOrBotCommandInsert(QString,FieldAutocomplete::ChooseMethod)));
connect(_fieldAutocomplete, SIGNAL(botCommandChosen(QString,FieldAutocomplete::ChooseMethod)), this, SLOT(onHashtagOrBotCommandInsert(QString,FieldAutocomplete::ChooseMethod))); connect(_fieldAutocomplete, SIGNAL(botCommandChosen(QString,FieldAutocomplete::ChooseMethod)), this, SLOT(onHashtagOrBotCommandInsert(QString,FieldAutocomplete::ChooseMethod)));
connect(_fieldAutocomplete, SIGNAL(stickerChosen(DocumentData*,FieldAutocomplete::ChooseMethod)), this, SLOT(onStickerSend(DocumentData*))); connect(_fieldAutocomplete, SIGNAL(stickerChosen(DocumentData*,FieldAutocomplete::ChooseMethod)), this, SLOT(onStickerSend(DocumentData*)));
connect(_fieldAutocomplete, SIGNAL(moderateKeyActivate(int,bool*)), this, SLOT(onModerateKeyActivate(int,bool*)));
_field.installEventFilter(_fieldAutocomplete); _field.installEventFilter(_fieldAutocomplete);
_field.setTagMimeProcessor(std_::make_unique<FieldTagMimeProcessor>()); _field.setTagMimeProcessor(std_::make_unique<FieldTagMimeProcessor>());
updateFieldSubmitSettings(); updateFieldSubmitSettings();
@ -5646,7 +5659,10 @@ bool HistoryWidget::eventFilter(QObject *obj, QEvent *e) {
} }
DragState HistoryWidget::getDragState(const QMimeData *d) { DragState HistoryWidget::getDragState(const QMimeData *d) {
if (!d || d->hasFormat(qsl("application/x-td-forward-pressed-link"))) return DragStateNone; if (!d
|| d->hasFormat(qsl("application/x-td-forward-selected"))
|| d->hasFormat(qsl("application/x-td-forward-pressed"))
|| d->hasFormat(qsl("application/x-td-forward-pressed-link"))) return DragStateNone;
if (d->hasImage()) return DragStateImage; if (d->hasImage()) return DragStateImage;
@ -6062,6 +6078,10 @@ void HistoryWidget::onMembersDropdownShow() {
_membersDropdown->otherEnter(); _membersDropdown->otherEnter();
} }
void HistoryWidget::onModerateKeyActivate(int index, bool *outHandled) {
*outHandled = _keyboard.isHidden() ? false : _keyboard.moderateKeyActivate(index);
}
void HistoryWidget::onMembersDropdownHidden() { void HistoryWidget::onMembersDropdownHidden() {
_membersDropdown.destroyDelayed(); _membersDropdown.destroyDelayed();
} }

View File

@ -364,6 +364,8 @@ public:
void enterEvent(QEvent *e) override; void enterEvent(QEvent *e) override;
void leaveEvent(QEvent *e) override; void leaveEvent(QEvent *e) override;
bool moderateKeyActivate(int index);
// With force=true the markup is updated even if it is // With force=true the markup is updated even if it is
// already shown for the passed history item. // already shown for the passed history item.
bool updateMarkup(HistoryItem *last, bool force = false); bool updateMarkup(HistoryItem *last, bool force = false);
@ -846,6 +848,8 @@ private slots:
void onMembersDropdownHidden(); void onMembersDropdownHidden();
void onMembersDropdownShow(); void onMembersDropdownShow();
void onModerateKeyActivate(int index, bool *outHandled);
void updateField(); void updateField();
private: private:

View File

@ -540,6 +540,7 @@ namespace {
dbiAdaptiveForWide = 0x38, dbiAdaptiveForWide = 0x38,
dbiHiddenPinnedMessages = 0x39, dbiHiddenPinnedMessages = 0x39,
dbiDialogsMode = 0x40, dbiDialogsMode = 0x40,
dbiModerateMode = 0x41,
dbiEncryptedWithSalt = 333, dbiEncryptedWithSalt = 333,
dbiEncrypted = 444, dbiEncrypted = 444,
@ -933,6 +934,14 @@ namespace {
Global::SetDialogsMode(mode); Global::SetDialogsMode(mode);
} break; } break;
case dbiModerateMode: {
qint32 enabled;
stream >> enabled;
if (!_checkStreamStatus(stream)) return false;
Global::SetModerateModeEnabled(enabled == 1);
} break;
case dbiIncludeMuted: { case dbiIncludeMuted: {
qint32 v; qint32 v;
stream >> v; stream >> v;
@ -1523,7 +1532,7 @@ namespace {
_writeMap(WriteMapFast); _writeMap(WriteMapFast);
} }
uint32 size = 16 * (sizeof(quint32) + sizeof(qint32)); uint32 size = 17 * (sizeof(quint32) + sizeof(qint32));
size += sizeof(quint32) + Serialize::stringSize(cAskDownloadPath() ? QString() : cDownloadPath()) + Serialize::bytearraySize(cAskDownloadPath() ? QByteArray() : cDownloadPathBookmark()); size += sizeof(quint32) + Serialize::stringSize(cAskDownloadPath() ? QString() : cDownloadPath()) + Serialize::bytearraySize(cAskDownloadPath() ? QByteArray() : cDownloadPathBookmark());
size += sizeof(quint32) + sizeof(qint32) + (cRecentEmojisPreload().isEmpty() ? cGetRecentEmojis().size() : cRecentEmojisPreload().size()) * (sizeof(uint64) + sizeof(ushort)); size += sizeof(quint32) + sizeof(qint32) + (cRecentEmojisPreload().isEmpty() ? cGetRecentEmojis().size() : cRecentEmojisPreload().size()) * (sizeof(uint64) + sizeof(ushort));
size += sizeof(quint32) + sizeof(qint32) + cEmojiVariants().size() * (sizeof(uint32) + sizeof(uint64)); size += sizeof(quint32) + sizeof(qint32) + cEmojiVariants().size() * (sizeof(uint32) + sizeof(uint64));
@ -1555,6 +1564,7 @@ namespace {
data.stream << quint32(dbiSongVolume) << qint32(qRound(cSongVolume() * 1e6)); data.stream << quint32(dbiSongVolume) << qint32(qRound(cSongVolume() * 1e6));
data.stream << quint32(dbiAutoDownload) << qint32(cAutoDownloadPhoto()) << qint32(cAutoDownloadAudio()) << qint32(cAutoDownloadGif()); data.stream << quint32(dbiAutoDownload) << qint32(cAutoDownloadPhoto()) << qint32(cAutoDownloadAudio()) << qint32(cAutoDownloadGif());
data.stream << quint32(dbiDialogsMode) << qint32(Global::DialogsModeEnabled() ? 1 : 0) << static_cast<qint32>(Global::DialogsMode()); data.stream << quint32(dbiDialogsMode) << qint32(Global::DialogsModeEnabled() ? 1 : 0) << static_cast<qint32>(Global::DialogsMode());
data.stream << quint32(dbiModerateMode) << qint32(Global::ModerateModeEnabled() ? 1 : 0);
data.stream << quint32(dbiAutoPlay) << qint32(cAutoPlayGif() ? 1 : 0); data.stream << quint32(dbiAutoPlay) << qint32(cAutoPlayGif() ? 1 : 0);
{ {

View File

@ -3215,7 +3215,7 @@ void MainWidget::getDifference() {
_getDifferenceTimeByPts = 0; _getDifferenceTimeByPts = 0;
LOG(("Getting difference! no updates timer: %1, remains: %2").arg(noUpdatesTimer.isActive() ? 1 : 0).arg(noUpdatesTimer.remainingTime())); LOG(("Getting difference! no updates timer: %1, remains: %2").arg(noUpdatesTimer.isActive() ? 1 : 0).arg(noUpdatesTimer.remainingTime()));
if (_ptsWaiter.requesting()) return; if (requestingDifference()) return;
_bySeqUpdates.clear(); _bySeqUpdates.clear();
_bySeqTimer.stop(); _bySeqTimer.stop();
@ -3879,7 +3879,7 @@ void MainWidget::updateReceived(const mtpPrime *from, const mtpPrime *end) {
_lastUpdateTime = getms(true); _lastUpdateTime = getms(true);
noUpdatesTimer.start(NoUpdatesTimeout); noUpdatesTimer.start(NoUpdatesTimeout);
if (!_ptsWaiter.requesting()) { if (!requestingDifference()) {
feedUpdates(updates); feedUpdates(updates);
} }
} catch (mtpErrorUnexpected &) { // just some other type } catch (mtpErrorUnexpected &) { // just some other type
@ -4195,8 +4195,10 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
if (item->isMediaUnread()) { if (item->isMediaUnread()) {
item->markMediaRead(); item->markMediaRead();
Ui::repaintHistoryItem(item); Ui::repaintHistoryItem(item);
if (item->out() && item->history()->peer->isUser()) { if (item->out() && item->history()->peer->isUser()) {
item->history()->peer->asUser()->madeAction(); auto when = requestingDifference() ? 0 : unixtime();
item->history()->peer->asUser()->madeAction(when);
} }
} }
} }
@ -4227,7 +4229,8 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
// update before applying skipped // update before applying skipped
auto peerId = peerFromMTP(d.vpeer); auto peerId = peerFromMTP(d.vpeer);
App::feedOutboxRead(peerId, d.vmax_id.v); auto when = requestingDifference() ? 0 : unixtime();
App::feedOutboxRead(peerId, d.vmax_id.v, when);
if (_history->peer() && _history->peer()->id == peerId) { if (_history->peer() && _history->peer()->id == peerId) {
_history->update(); _history->update();
} }
@ -4269,7 +4272,8 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
History *history = App::historyLoaded(peerFromUser(d.vuser_id)); History *history = App::historyLoaded(peerFromUser(d.vuser_id));
UserData *user = App::userLoaded(d.vuser_id.v); UserData *user = App::userLoaded(d.vuser_id.v);
if (history && user) { if (history && user) {
App::histories().regSendAction(history, user, d.vaction); auto when = requestingDifference() ? 0 : unixtime();
App::histories().regSendAction(history, user, d.vaction, when);
} }
} break; } break;
@ -4283,7 +4287,8 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
} }
UserData *user = (d.vuser_id.v == MTP::authedId()) ? 0 : App::userLoaded(d.vuser_id.v); UserData *user = (d.vuser_id.v == MTP::authedId()) ? 0 : App::userLoaded(d.vuser_id.v);
if (history && user) { if (history && user) {
App::histories().regSendAction(history, user, d.vaction); auto when = requestingDifference() ? 0 : unixtime();
App::histories().regSendAction(history, user, d.vaction, when);
} }
} break; } break;
@ -4481,7 +4486,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
const auto &d(update.c_updateNewChannelMessage()); const auto &d(update.c_updateNewChannelMessage());
ChannelData *channel = App::channelLoaded(peerToChannel(peerFromMessage(d.vmessage))); ChannelData *channel = App::channelLoaded(peerToChannel(peerFromMessage(d.vmessage)));
DataIsLoadedResult isDataLoaded = allDataLoadedForMessage(d.vmessage); DataIsLoadedResult isDataLoaded = allDataLoadedForMessage(d.vmessage);
if (!_ptsWaiter.requesting() && (!channel || isDataLoaded != DataIsLoadedResult::Ok)) { if (!requestingDifference() && (!channel || isDataLoaded != DataIsLoadedResult::Ok)) {
MTP_LOG(0, ("getDifference { good - after not all data loaded in updateNewChannelMessage }%1").arg(cTestMode() ? " TESTMODE" : "")); MTP_LOG(0, ("getDifference { good - after not all data loaded in updateNewChannelMessage }%1").arg(cTestMode() ? " TESTMODE" : ""));
// Request last active supergroup participants if the 'from' user was not loaded yet. // Request last active supergroup participants if the 'from' user was not loaded yet.
@ -4586,7 +4591,8 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
case mtpc_updateReadChannelOutbox: { case mtpc_updateReadChannelOutbox: {
auto &d(update.c_updateReadChannelOutbox()); auto &d(update.c_updateReadChannelOutbox());
auto peerId = peerFromChannel(d.vchannel_id.v); auto peerId = peerFromChannel(d.vchannel_id.v);
App::feedOutboxRead(peerId, d.vmax_id.v); auto when = requestingDifference() ? 0 : unixtime();
App::feedOutboxRead(peerId, d.vmax_id.v, when);
if (_history->peer() && _history->peer()->id == peerId) { if (_history->peer() && _history->peer()->id == peerId) {
_history->update(); _history->update();
} }

View File

@ -618,6 +618,9 @@ private:
bool ptsUpdated(int32 pts, int32 ptsCount, const MTPUpdate &update); bool ptsUpdated(int32 pts, int32 ptsCount, const MTPUpdate &update);
void ptsApplySkippedUpdates(); void ptsApplySkippedUpdates();
PtsWaiter _ptsWaiter; PtsWaiter _ptsWaiter;
bool requestingDifference() const {
return _ptsWaiter.requesting();
}
typedef QMap<ChannelData*, uint64> ChannelGetDifferenceTime; typedef QMap<ChannelData*, uint64> ChannelGetDifferenceTime;
ChannelGetDifferenceTime _channelGetDifferenceTimeByPts, _channelGetDifferenceTimeAfterFail; ChannelGetDifferenceTime _channelGetDifferenceTimeByPts, _channelGetDifferenceTimeAfterFail;

View File

@ -437,7 +437,7 @@ QString getImage(const StorageKey &key, PeerData *peer) {
} }
v.path = cWorkingDir() + qsl("tdata/temp/") + QString::number(rand_value<uint64>(), 16) + qsl(".png"); v.path = cWorkingDir() + qsl("tdata/temp/") + QString::number(rand_value<uint64>(), 16) + qsl(".png");
if (key.first || key.second) { if (key.first || key.second) {
peer->saveUserpic(v.path); peer->saveUserpic(v.path, st::notifyMacPhotoSize);
} else { } else {
App::wnd()->iconLarge().save(v.path, "PNG"); App::wnd()->iconLarge().save(v.path, "PNG");
} }

View File

@ -824,6 +824,7 @@ void SettingsInner::keyPressEvent(QKeyEvent *e) {
break; break;
} else if (str == qstr("loadlang")) { } else if (str == qstr("loadlang")) {
chooseCustomLang(); chooseCustomLang();
break;
} else if (str == qstr("debugfiles") && cDebug()) { } else if (str == qstr("debugfiles") && cDebug()) {
if (DebugLogging::FileLoader()) { if (DebugLogging::FileLoader()) {
Global::RefDebugLoggingFlags() &= ~DebugLogging::FileLoaderFlag; Global::RefDebugLoggingFlags() &= ~DebugLogging::FileLoaderFlag;
@ -831,19 +832,34 @@ void SettingsInner::keyPressEvent(QKeyEvent *e) {
Global::RefDebugLoggingFlags() |= DebugLogging::FileLoaderFlag; Global::RefDebugLoggingFlags() |= DebugLogging::FileLoaderFlag;
} }
Ui::showLayer(new InformBox(DebugLogging::FileLoader() ? qsl("Enabled file download logging") : qsl("Disabled file download logging"))); Ui::showLayer(new InformBox(DebugLogging::FileLoader() ? qsl("Enabled file download logging") : qsl("Disabled file download logging")));
break;
} else if (str == qstr("crashplease")) { } else if (str == qstr("crashplease")) {
t_assert(!"Crashed in Settings!"); t_assert(!"Crashed in Settings!");
break;
} else if (str == qstr("workmode")) { } else if (str == qstr("workmode")) {
QString text = Global::DialogsModeEnabled() ? qsl("Disable work mode?") : qsl("Enable work mode?"); auto text = Global::DialogsModeEnabled() ? qsl("Disable work mode?") : qsl("Enable work mode?");
auto box = std_::make_unique<ConfirmBox>(text); auto box = std_::make_unique<ConfirmBox>(text);
connect(box.get(), SIGNAL(confirmed()), App::app(), SLOT(onSwitchWorkMode())); connect(box.get(), SIGNAL(confirmed()), App::app(), SLOT(onSwitchWorkMode()));
Ui::showLayer(box.release()); Ui::showLayer(box.release());
from = size; from = size;
break; break;
} else if (str == qstr("moderate")) {
auto text = Global::ModerateModeEnabled() ? qsl("Disable moderate mode?") : qsl("Enable moderate mode?");
auto box = std_::make_unique<ConfirmBox>(text);
connect(box.get(), SIGNAL(confirmed()), this, SLOT(onSwitchModerateMode()));
Ui::showLayer(box.release());
break;
} else if (str == qstr("clearstickers")) {
auto box = std_::make_unique<ConfirmBox>(qsl("Clear frequently used stickers list?"));
connect(box.get(), SIGNAL(confirmed()), this, SLOT(onClearStickers()));
Ui::showLayer(box.release());
break;
} else if ( } else if (
qsl("debugmode").startsWith(str) || qsl("debugmode").startsWith(str) ||
qsl("testmode").startsWith(str) || qsl("testmode").startsWith(str) ||
qsl("loadlang").startsWith(str) || qsl("loadlang").startsWith(str) ||
qsl("clearstickers").startsWith(str) ||
qsl("moderate").startsWith(str) ||
qsl("debugfiles").startsWith(str) || qsl("debugfiles").startsWith(str) ||
qsl("workmode").startsWith(str) || qsl("workmode").startsWith(str) ||
qsl("crashplease").startsWith(str)) { qsl("crashplease").startsWith(str)) {
@ -1251,6 +1267,30 @@ void SettingsInner::onShowSessions() {
Ui::showLayer(box); Ui::showLayer(box);
} }
void SettingsInner::onClearStickers() {
auto &recent(cGetRecentStickers());
if (!recent.isEmpty()) {
recent.clear();
Local::writeUserSettings();
}
auto &sets(Global::RefStickerSets());
auto it = sets.find(Stickers::CustomSetId);
if (it != sets.cend()) {
sets.erase(it);
Local::writeStickers();
}
if (auto m = App::main()) {
emit m->stickersUpdated();
}
Ui::hideLayer();
}
void SettingsInner::onSwitchModerateMode() {
Global::SetModerateModeEnabled(!Global::ModerateModeEnabled());
Local::writeUserSettings();
Ui::hideLayer();
}
void SettingsInner::onAskQuestion() { void SettingsInner::onAskQuestion() {
if (!App::self()) return; if (!App::self()) return;

View File

@ -186,6 +186,10 @@ public slots:
void onUpdateLocalStorage(); void onUpdateLocalStorage();
private slots:
void onClearStickers();
void onSwitchModerateMode();
void onAskQuestion(); void onAskQuestion();
void onAskQuestionSure(); void onAskQuestionSure();
void onTelegramFAQ(); void onTelegramFAQ();

View File

@ -185,12 +185,12 @@ StorageKey PeerData::userpicUniqueKey() const {
return storageKey(photoLoc); return storageKey(photoLoc);
} }
void PeerData::saveUserpic(const QString &path) const { void PeerData::saveUserpic(const QString &path, int size) const {
currentUserpic()->pixCircled().save(path, "PNG"); currentUserpic()->pixRounded(size, size).save(path, "PNG");
} }
QPixmap PeerData::genUserpic(int size) const { QPixmap PeerData::genUserpic(int size) const {
return currentUserpic()->pixCircled(size, size); return currentUserpic()->pixRounded(size, size);
} }
const Text &BotCommand::descriptionText() const { const Text &BotCommand::descriptionText() const {
@ -373,16 +373,15 @@ void UserData::setNameOrPhone(const QString &newNameOrPhone) {
} }
} }
void UserData::madeAction() { void UserData::madeAction(TimeId when) {
if (botInfo || isServiceUser(id)) return; if (botInfo || isServiceUser(id) || when <= 0) return;
int32 t = unixtime(); if (onlineTill <= 0 && -onlineTill < when) {
if (onlineTill <= 0 && -onlineTill < t) { onlineTill = -when - SetOnlineAfterActivity;
onlineTill = -t - SetOnlineAfterActivity;
App::markPeerUpdated(this); App::markPeerUpdated(this);
Notify::peerUpdatedDelayed(this, Notify::PeerUpdate::Flag::UserOnlineChanged); Notify::peerUpdatedDelayed(this, Notify::PeerUpdate::Flag::UserOnlineChanged);
} else if (onlineTill > 0 && onlineTill < t + 1) { } else if (onlineTill > 0 && onlineTill < when + 1) {
onlineTill = t + SetOnlineAfterActivity; onlineTill = when + SetOnlineAfterActivity;
App::markPeerUpdated(this); App::markPeerUpdated(this);
Notify::peerUpdatedDelayed(this, Notify::PeerUpdate::Flag::UserOnlineChanged); Notify::peerUpdatedDelayed(this, Notify::PeerUpdate::Flag::UserOnlineChanged);
} }

View File

@ -315,7 +315,7 @@ public:
return _userpic->loaded(); return _userpic->loaded();
} }
StorageKey userpicUniqueKey() const; StorageKey userpicUniqueKey() const;
void saveUserpic(const QString &path) const; void saveUserpic(const QString &path, int size) const;
QPixmap genUserpic(int size) const; QPixmap genUserpic(int size) const;
PhotoId photoId = UnknownPeerPhotoId; PhotoId photoId = UnknownPeerPhotoId;
@ -406,7 +406,7 @@ public:
void setNameOrPhone(const QString &newNameOrPhone); void setNameOrPhone(const QString &newNameOrPhone);
void madeAction(); // pseudo-online void madeAction(TimeId when); // pseudo-online
uint64 access = 0; uint64 access = 0;

View File

@ -2375,7 +2375,7 @@
SDKROOT = macosx; SDKROOT = macosx;
SYMROOT = ./../Mac; SYMROOT = ./../Mac;
TDESKTOP_MAJOR_VERSION = 0.9; TDESKTOP_MAJOR_VERSION = 0.9;
TDESKTOP_VERSION = 0.9.53; TDESKTOP_VERSION = 0.9.54;
}; };
name = Release; name = Release;
}; };
@ -2516,7 +2516,7 @@
SDKROOT = macosx; SDKROOT = macosx;
SYMROOT = ./../Mac; SYMROOT = ./../Mac;
TDESKTOP_MAJOR_VERSION = 0.9; TDESKTOP_MAJOR_VERSION = 0.9;
TDESKTOP_VERSION = 0.9.53; TDESKTOP_VERSION = 0.9.54;
}; };
name = Debug; name = Debug;
}; };

View File

@ -1,6 +1,6 @@
AppVersion 9053 AppVersion 9054
AppVersionStrMajor 0.9 AppVersionStrMajor 0.9
AppVersionStrSmall 0.9.53 AppVersionStrSmall 0.9.54
AppVersionStr 0.9.53 AppVersionStr 0.9.54
AlphaChannel 1 AlphaChannel 1
BetaVersion 0 BetaVersion 0