mirror of https://github.com/procxx/kepka.git
Display occupied chats using drafts for support.
This commit is contained in:
parent
60103f7ad6
commit
4960e08a24
|
@ -2193,7 +2193,11 @@ void ApiWrap::saveDraftsToCloud() {
|
||||||
if (cloudDraft && cloudDraft->saveRequestId) {
|
if (cloudDraft && cloudDraft->saveRequestId) {
|
||||||
request(base::take(cloudDraft->saveRequestId)).cancel();
|
request(base::take(cloudDraft->saveRequestId)).cancel();
|
||||||
}
|
}
|
||||||
|
if (!Auth().supportMode()) {
|
||||||
cloudDraft = history->createCloudDraft(localDraft);
|
cloudDraft = history->createCloudDraft(localDraft);
|
||||||
|
} else if (!cloudDraft) {
|
||||||
|
cloudDraft = history->createCloudDraft(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
auto flags = MTPmessages_SaveDraft::Flags(0);
|
auto flags = MTPmessages_SaveDraft::Flags(0);
|
||||||
auto &textWithTags = cloudDraft->textWithTags;
|
auto &textWithTags = cloudDraft->textWithTags;
|
||||||
|
|
|
@ -25,7 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "boxes/send_files_box.h"
|
#include "boxes/send_files_box.h"
|
||||||
#include "ui/widgets/input_fields.h"
|
#include "ui/widgets/input_fields.h"
|
||||||
#include "support/support_common.h"
|
#include "support/support_common.h"
|
||||||
#include "support/support_templates.h"
|
#include "support/support_helper.h"
|
||||||
#include "observer_peer.h"
|
#include "observer_peer.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -342,9 +342,9 @@ AuthSession::AuthSession(const MTPUser &user)
|
||||||
, _notifications(std::make_unique<Window::Notifications::System>(this))
|
, _notifications(std::make_unique<Window::Notifications::System>(this))
|
||||||
, _data(std::make_unique<Data::Session>(this))
|
, _data(std::make_unique<Data::Session>(this))
|
||||||
, _changelogs(Core::Changelogs::Create(this))
|
, _changelogs(Core::Changelogs::Create(this))
|
||||||
, _supportTemplates(
|
, _supportHelper(
|
||||||
(Support::ValidateAccount(user)
|
(Support::ValidateAccount(user)
|
||||||
? std::make_unique<Support::Templates>(this)
|
? std::make_unique<Support::Helper>(this)
|
||||||
: nullptr)) {
|
: nullptr)) {
|
||||||
App::feedUser(user);
|
App::feedUser(user);
|
||||||
|
|
||||||
|
@ -457,13 +457,17 @@ void AuthSession::checkAutoLockIn(TimeMs time) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AuthSession::supportMode() const {
|
bool AuthSession::supportMode() const {
|
||||||
return (_supportTemplates != nullptr);
|
return (_supportHelper != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
not_null<Support::Templates*> AuthSession::supportTemplates() const {
|
Support::Helper &AuthSession::supportHelper() const {
|
||||||
Expects(supportMode());
|
Expects(supportMode());
|
||||||
|
|
||||||
return _supportTemplates.get();
|
return *_supportHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
Support::Templates& AuthSession::supportTemplates() const {
|
||||||
|
return supportHelper().templates();
|
||||||
}
|
}
|
||||||
|
|
||||||
AuthSession::~AuthSession() = default;
|
AuthSession::~AuthSession() = default;
|
||||||
|
|
|
@ -21,6 +21,7 @@ enum class InputSubmitSettings;
|
||||||
|
|
||||||
namespace Support {
|
namespace Support {
|
||||||
enum class SwitchSettings;
|
enum class SwitchSettings;
|
||||||
|
class Helper;
|
||||||
class Templates;
|
class Templates;
|
||||||
} // namespace Support
|
} // namespace Support
|
||||||
|
|
||||||
|
@ -301,7 +302,8 @@ public:
|
||||||
base::Observable<std::pair<not_null<HistoryItem*>, MsgId>> messageIdChanging;
|
base::Observable<std::pair<not_null<HistoryItem*>, MsgId>> messageIdChanging;
|
||||||
|
|
||||||
bool supportMode() const;
|
bool supportMode() const;
|
||||||
not_null<Support::Templates*> supportTemplates() const;
|
Support::Helper &supportHelper() const;
|
||||||
|
Support::Templates &supportTemplates() const;
|
||||||
|
|
||||||
~AuthSession();
|
~AuthSession();
|
||||||
|
|
||||||
|
@ -328,7 +330,7 @@ private:
|
||||||
// _changelogs depends on _data, subscribes on chats loading event.
|
// _changelogs depends on _data, subscribes on chats loading event.
|
||||||
const std::unique_ptr<Core::Changelogs> _changelogs;
|
const std::unique_ptr<Core::Changelogs> _changelogs;
|
||||||
|
|
||||||
const std::unique_ptr<Support::Templates> _supportTemplates;
|
const std::unique_ptr<Support::Helper> _supportHelper;
|
||||||
|
|
||||||
rpl::lifetime _lifetime;
|
rpl::lifetime _lifetime;
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "history/history_widget.h"
|
#include "history/history_widget.h"
|
||||||
#include "mainwidget.h"
|
#include "mainwidget.h"
|
||||||
#include "storage/localstorage.h"
|
#include "storage/localstorage.h"
|
||||||
|
#include "support/support_helper.h"
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -44,8 +45,8 @@ Draft::Draft(
|
||||||
}
|
}
|
||||||
|
|
||||||
void applyPeerCloudDraft(PeerId peerId, const MTPDdraftMessage &draft) {
|
void applyPeerCloudDraft(PeerId peerId, const MTPDdraftMessage &draft) {
|
||||||
auto history = App::history(peerId);
|
const auto history = App::history(peerId);
|
||||||
auto textWithTags = TextWithTags {
|
const auto textWithTags = TextWithTags {
|
||||||
qs(draft.vmessage),
|
qs(draft.vmessage),
|
||||||
ConvertEntitiesToTextTags(
|
ConvertEntitiesToTextTags(
|
||||||
draft.has_entities()
|
draft.has_entities()
|
||||||
|
@ -56,14 +57,23 @@ void applyPeerCloudDraft(PeerId peerId, const MTPDdraftMessage &draft) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto replyTo = draft.has_reply_to_msg_id() ? draft.vreply_to_msg_id.v : MsgId(0);
|
auto replyTo = draft.has_reply_to_msg_id() ? draft.vreply_to_msg_id.v : MsgId(0);
|
||||||
auto cloudDraft = std::make_unique<Draft>(textWithTags, replyTo, MessageCursor(QFIXED_MAX, QFIXED_MAX, QFIXED_MAX), draft.is_no_webpage());
|
auto cloudDraft = std::make_unique<Draft>(
|
||||||
|
textWithTags,
|
||||||
|
replyTo,
|
||||||
|
MessageCursor(QFIXED_MAX, QFIXED_MAX, QFIXED_MAX),
|
||||||
|
draft.is_no_webpage());
|
||||||
cloudDraft->date = draft.vdate.v;
|
cloudDraft->date = draft.vdate.v;
|
||||||
|
|
||||||
history->setCloudDraft(std::move(cloudDraft));
|
history->setCloudDraft(std::move(cloudDraft));
|
||||||
history->createLocalDraftFromCloud();
|
history->createLocalDraftFromCloud();
|
||||||
|
if (Auth().supportMode()) {
|
||||||
|
history->updateChatListEntry();
|
||||||
|
Auth().supportHelper().cloudDraftChanged(history);
|
||||||
|
} else {
|
||||||
history->updateChatListSortPosition();
|
history->updateChatListSortPosition();
|
||||||
|
}
|
||||||
|
|
||||||
if (auto main = App::main()) {
|
if (const auto main = App::main()) {
|
||||||
main->applyCloudDraft(history);
|
main->applyCloudDraft(history);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,7 +87,12 @@ void clearPeerCloudDraft(PeerId peerId, TimeId date) {
|
||||||
history->clearCloudDraft();
|
history->clearCloudDraft();
|
||||||
history->clearLocalDraft();
|
history->clearLocalDraft();
|
||||||
|
|
||||||
|
if (Auth().supportMode()) {
|
||||||
|
history->updateChatListEntry();
|
||||||
|
Auth().supportHelper().cloudDraftChanged(history);
|
||||||
|
} else {
|
||||||
history->updateChatListSortPosition();
|
history->updateChatListSortPosition();
|
||||||
|
}
|
||||||
|
|
||||||
if (auto main = App::main()) {
|
if (auto main = App::main()) {
|
||||||
main->applyCloudDraft(history);
|
main->applyCloudDraft(history);
|
||||||
|
|
|
@ -47,11 +47,12 @@ inline bool draftStringIsEmpty(const QString &text) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool draftIsNull(Draft *draft) {
|
inline bool draftIsNull(const Draft *draft) {
|
||||||
return !draft || (draftStringIsEmpty(draft->textWithTags.text) && !draft->msgId);
|
return !draft
|
||||||
|
|| (draftStringIsEmpty(draft->textWithTags.text) && !draft->msgId);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool draftsAreEqual(Draft *a, Draft *b) {
|
inline bool draftsAreEqual(const Draft *a, const Draft *b) {
|
||||||
bool aIsNull = draftIsNull(a);
|
bool aIsNull = draftIsNull(a);
|
||||||
bool bIsNull = draftIsNull(b);
|
bool bIsNull = draftIsNull(b);
|
||||||
if (aIsNull) {
|
if (aIsNull) {
|
||||||
|
@ -60,7 +61,9 @@ inline bool draftsAreEqual(Draft *a, Draft *b) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (a->textWithTags == b->textWithTags) && (a->msgId == b->msgId) && (a->previewCancelled == b->previewCancelled);
|
return (a->textWithTags == b->textWithTags)
|
||||||
|
&& (a->msgId == b->msgId)
|
||||||
|
&& (a->previewCancelled == b->previewCancelled);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
|
@ -55,7 +55,7 @@ Row *IndexedList::addByName(Key key) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void IndexedList::adjustByPos(const RowsByLetter &links) {
|
void IndexedList::adjustByPos(const RowsByLetter &links) {
|
||||||
for (auto [ch, row] : links) {
|
for (const auto [ch, row] : links) {
|
||||||
if (ch == QChar(0)) {
|
if (ch == QChar(0)) {
|
||||||
_list.adjustByPos(row);
|
_list.adjustByPos(row);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -124,7 +124,8 @@ DialogsInner::DialogsInner(QWidget *parent, not_null<Window::Controller*> contro
|
||||||
auto changes = UpdateFlag::ChatPinnedChanged
|
auto changes = UpdateFlag::ChatPinnedChanged
|
||||||
| UpdateFlag::NameChanged
|
| UpdateFlag::NameChanged
|
||||||
| UpdateFlag::PhotoChanged
|
| UpdateFlag::PhotoChanged
|
||||||
| UpdateFlag::UserIsContact;
|
| UpdateFlag::UserIsContact
|
||||||
|
| UpdateFlag::OccupiedChanged;
|
||||||
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(changes, [this](const Notify::PeerUpdate &update) {
|
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(changes, [this](const Notify::PeerUpdate &update) {
|
||||||
if (update.flags & UpdateFlag::ChatPinnedChanged) {
|
if (update.flags & UpdateFlag::ChatPinnedChanged) {
|
||||||
stopReorderPinned();
|
stopReorderPinned();
|
||||||
|
@ -132,7 +133,7 @@ DialogsInner::DialogsInner(QWidget *parent, not_null<Window::Controller*> contro
|
||||||
if (update.flags & UpdateFlag::NameChanged) {
|
if (update.flags & UpdateFlag::NameChanged) {
|
||||||
handlePeerNameChange(update.peer, update.oldNameFirstLetters);
|
handlePeerNameChange(update.peer, update.oldNameFirstLetters);
|
||||||
}
|
}
|
||||||
if (update.flags & UpdateFlag::PhotoChanged) {
|
if (update.flags & (UpdateFlag::PhotoChanged | UpdateFlag::OccupiedChanged)) {
|
||||||
this->update();
|
this->update();
|
||||||
emit App::main()->dialogsUpdated();
|
emit App::main()->dialogsUpdated();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/empty_userpic.h"
|
#include "ui/empty_userpic.h"
|
||||||
#include "ui/text_options.h"
|
#include "ui/text_options.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
|
#include "support/support_helper.h"
|
||||||
#include "history/history_item.h"
|
#include "history/history_item.h"
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
|
|
||||||
|
@ -173,6 +174,11 @@ void paintRow(
|
||||||
TimeMs ms,
|
TimeMs ms,
|
||||||
PaintItemCallback &&paintItemCallback,
|
PaintItemCallback &&paintItemCallback,
|
||||||
PaintCounterCallback &&paintCounterCallback) {
|
PaintCounterCallback &&paintCounterCallback) {
|
||||||
|
const auto supportMode = Auth().supportMode();
|
||||||
|
if (supportMode) {
|
||||||
|
draft = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
auto active = (flags & Flag::Active);
|
auto active = (flags & Flag::Active);
|
||||||
auto selected = (flags & Flag::Selected);
|
auto selected = (flags & Flag::Selected);
|
||||||
auto fullRect = QRect(0, 0, fullWidth, st::dialogsRowHeight);
|
auto fullRect = QRect(0, 0, fullWidth, st::dialogsRowHeight);
|
||||||
|
@ -250,7 +256,7 @@ void paintRow(
|
||||||
auto texttop = st::dialogsPadding.y()
|
auto texttop = st::dialogsPadding.y()
|
||||||
+ st::msgNameFont->height
|
+ st::msgNameFont->height
|
||||||
+ st::dialogsSkip;
|
+ st::dialogsSkip;
|
||||||
if (draft) {
|
if (draft || (supportMode && Support::IsOccupiedBySomeone(history))) {
|
||||||
if (!promoted) {
|
if (!promoted) {
|
||||||
paintRowDate(p, date, rectForName, active, selected);
|
paintRowDate(p, date, rectForName, active, selected);
|
||||||
}
|
}
|
||||||
|
@ -267,7 +273,9 @@ void paintRow(
|
||||||
if (history && !history->paintSendAction(p, nameleft, texttop, availableWidth, fullWidth, color, ms)) {
|
if (history && !history->paintSendAction(p, nameleft, texttop, availableWidth, fullWidth, color, ms)) {
|
||||||
if (history->cloudDraftTextCache.isEmpty()) {
|
if (history->cloudDraftTextCache.isEmpty()) {
|
||||||
auto draftWrapped = textcmdLink(1, lng_dialogs_text_from_wrapped(lt_from, lang(lng_from_draft)));
|
auto draftWrapped = textcmdLink(1, lng_dialogs_text_from_wrapped(lt_from, lang(lng_from_draft)));
|
||||||
auto draftText = lng_dialogs_text_with_from(lt_from_part, draftWrapped, lt_message, TextUtilities::Clean(draft->textWithTags.text));
|
auto draftText = supportMode
|
||||||
|
? textcmdLink(1, Support::ChatOccupiedString())
|
||||||
|
: lng_dialogs_text_with_from(lt_from_part, draftWrapped, lt_message, TextUtilities::Clean(draft->textWithTags.text));
|
||||||
history->cloudDraftTextCache.setText(st::dialogsTextStyle, draftText, Ui::DialogTextOptions());
|
history->cloudDraftTextCache.setText(st::dialogsTextStyle, draftText, Ui::DialogTextOptions());
|
||||||
}
|
}
|
||||||
p.setPen(active ? st::dialogsTextFgActive : (selected ? st::dialogsTextFgOver : st::dialogsTextFg));
|
p.setPen(active ? st::dialogsTextFgActive : (selected ? st::dialogsTextFgOver : st::dialogsTextFg));
|
||||||
|
|
|
@ -348,12 +348,14 @@ void History::takeLocalDraft(History *from) {
|
||||||
|
|
||||||
void History::createLocalDraftFromCloud() {
|
void History::createLocalDraftFromCloud() {
|
||||||
auto draft = cloudDraft();
|
auto draft = cloudDraft();
|
||||||
if (Data::draftIsNull(draft) || !draft->date) {
|
if (Data::draftIsNull(draft) || !draft->date || Auth().supportMode()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto existing = localDraft();
|
auto existing = localDraft();
|
||||||
if (Data::draftIsNull(existing) || !existing->date || draft->date >= existing->date) {
|
if (Data::draftIsNull(existing)
|
||||||
|
|| !existing->date
|
||||||
|
|| draft->date >= existing->date) {
|
||||||
if (!existing) {
|
if (!existing) {
|
||||||
setLocalDraft(std::make_unique<Data::Draft>(
|
setLocalDraft(std::make_unique<Data::Draft>(
|
||||||
draft->textWithTags,
|
draft->textWithTags,
|
||||||
|
@ -376,7 +378,7 @@ void History::setCloudDraft(std::unique_ptr<Data::Draft> &&draft) {
|
||||||
cloudDraftTextCache.clear();
|
cloudDraftTextCache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
Data::Draft *History::createCloudDraft(Data::Draft *fromDraft) {
|
Data::Draft *History::createCloudDraft(const Data::Draft *fromDraft) {
|
||||||
if (Data::draftIsNull(fromDraft)) {
|
if (Data::draftIsNull(fromDraft)) {
|
||||||
setCloudDraft(std::make_unique<Data::Draft>(
|
setCloudDraft(std::make_unique<Data::Draft>(
|
||||||
TextWithTags(),
|
TextWithTags(),
|
||||||
|
@ -1830,7 +1832,7 @@ std::shared_ptr<AdminLog::LocalIdManager> History::adminLogIdManager() {
|
||||||
TimeId History::adjustChatListTimeId() const {
|
TimeId History::adjustChatListTimeId() const {
|
||||||
const auto result = chatsListTimeId();
|
const auto result = chatsListTimeId();
|
||||||
if (const auto draft = cloudDraft()) {
|
if (const auto draft = cloudDraft()) {
|
||||||
if (!Data::draftIsNull(draft)) {
|
if (!Data::draftIsNull(draft) && !Auth().supportMode()) {
|
||||||
return std::max(result, draft->date);
|
return std::max(result, draft->date);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -306,7 +306,7 @@ public:
|
||||||
void takeLocalDraft(History *from);
|
void takeLocalDraft(History *from);
|
||||||
void createLocalDraftFromCloud();
|
void createLocalDraftFromCloud();
|
||||||
void setCloudDraft(std::unique_ptr<Data::Draft> &&draft);
|
void setCloudDraft(std::unique_ptr<Data::Draft> &&draft);
|
||||||
Data::Draft *createCloudDraft(Data::Draft *fromDraft);
|
Data::Draft *createCloudDraft(const Data::Draft *fromDraft);
|
||||||
bool skipCloudDraft(const QString &text, TimeId date) const;
|
bool skipCloudDraft(const QString &text, TimeId date) const;
|
||||||
void setSentDraftText(const QString &text);
|
void setSentDraftText(const QString &text);
|
||||||
void clearSentDraftText(const QString &text);
|
void clearSentDraftText(const QString &text);
|
||||||
|
|
|
@ -30,6 +30,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "calls/calls_instance.h"
|
#include "calls/calls_instance.h"
|
||||||
#include "data/data_peer_values.h"
|
#include "data/data_peer_values.h"
|
||||||
#include "data/data_feed.h"
|
#include "data/data_feed.h"
|
||||||
|
#include "support/support_helper.h"
|
||||||
#include "observer_peer.h"
|
#include "observer_peer.h"
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
#include "styles/style_window.h"
|
#include "styles/style_window.h"
|
||||||
|
@ -52,6 +53,7 @@ TopBarWidget::TopBarWidget(
|
||||||
, _search(this, st::topBarSearch)
|
, _search(this, st::topBarSearch)
|
||||||
, _infoToggle(this, st::topBarInfo)
|
, _infoToggle(this, st::topBarInfo)
|
||||||
, _menuToggle(this, st::topBarMenuToggle)
|
, _menuToggle(this, st::topBarMenuToggle)
|
||||||
|
, _titlePeerText(st::windowMinWidth / 3)
|
||||||
, _onlineUpdater([this] { updateOnlineDisplay(); }) {
|
, _onlineUpdater([this] { updateOnlineDisplay(); }) {
|
||||||
subscribe(Lang::Current().updated(), [this] { refreshLang(); });
|
subscribe(Lang::Current().updated(), [this] { refreshLang(); });
|
||||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||||
|
@ -104,7 +106,8 @@ TopBarWidget::TopBarWidget(
|
||||||
using UpdateFlag = Notify::PeerUpdate::Flag;
|
using UpdateFlag = Notify::PeerUpdate::Flag;
|
||||||
auto flags = UpdateFlag::UserHasCalls
|
auto flags = UpdateFlag::UserHasCalls
|
||||||
| UpdateFlag::UserOnlineChanged
|
| UpdateFlag::UserOnlineChanged
|
||||||
| UpdateFlag::MembersChanged;
|
| UpdateFlag::MembersChanged
|
||||||
|
| UpdateFlag::OccupiedChanged;
|
||||||
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(flags, [this](const Notify::PeerUpdate &update) {
|
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(flags, [this](const Notify::PeerUpdate &update) {
|
||||||
if (update.flags & UpdateFlag::UserHasCalls) {
|
if (update.flags & UpdateFlag::UserHasCalls) {
|
||||||
if (update.peer->isUser()) {
|
if (update.peer->isUser()) {
|
||||||
|
@ -331,7 +334,8 @@ void TopBarWidget::paintTopBar(Painter &p, TimeMs ms) {
|
||||||
p.setFont(st::dialogsTextFont);
|
p.setFont(st::dialogsTextFont);
|
||||||
if (paintConnectingState(p, nameleft, statustop, width(), ms)) {
|
if (paintConnectingState(p, nameleft, statustop, width(), ms)) {
|
||||||
return;
|
return;
|
||||||
} else if (history->paintSendAction(
|
} else if (!Support::IsOccupiedBySomeone(history)
|
||||||
|
&& history->paintSendAction(
|
||||||
p,
|
p,
|
||||||
nameleft,
|
nameleft,
|
||||||
statustop,
|
statustop,
|
||||||
|
@ -379,25 +383,20 @@ void TopBarWidget::paintStatus(
|
||||||
int top,
|
int top,
|
||||||
int availableWidth,
|
int availableWidth,
|
||||||
int outerWidth) {
|
int outerWidth) {
|
||||||
auto statustext = _titlePeerText;
|
const auto occupied = Auth().supportMode()
|
||||||
auto statuswidth = _titlePeerTextWidth;
|
&& Support::IsOccupiedBySomeone(_activeChat.history());
|
||||||
if (statuswidth > availableWidth) {
|
p.setPen(occupied
|
||||||
statustext = st::dialogsTextFont->elided(
|
? st::dialogsTextPaletteDraft.linkFg
|
||||||
statustext,
|
: _titlePeerTextOnline
|
||||||
availableWidth,
|
|
||||||
Qt::ElideLeft);
|
|
||||||
statuswidth = st::dialogsTextFont->width(statustext);
|
|
||||||
}
|
|
||||||
p.setPen(_titlePeerTextOnline
|
|
||||||
? st::historyStatusFgActive
|
? st::historyStatusFgActive
|
||||||
: st::historyStatusFg);
|
: st::historyStatusFg);
|
||||||
p.drawTextLeft(left, top, outerWidth, statustext, statuswidth);
|
_titlePeerText.drawLeftElided(p, left, top, availableWidth, outerWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
QRect TopBarWidget::getMembersShowAreaGeometry() const {
|
QRect TopBarWidget::getMembersShowAreaGeometry() const {
|
||||||
int membersTextLeft = _leftTaken;
|
int membersTextLeft = _leftTaken;
|
||||||
int membersTextTop = st::topBarHeight - st::topBarArrowPadding.bottom() - st::dialogsTextFont->height;
|
int membersTextTop = st::topBarHeight - st::topBarArrowPadding.bottom() - st::dialogsTextFont->height;
|
||||||
int membersTextWidth = _titlePeerTextWidth;
|
int membersTextWidth = _titlePeerText.maxWidth();
|
||||||
int membersTextHeight = st::topBarHeight - membersTextTop;
|
int membersTextHeight = st::topBarHeight - membersTextTop;
|
||||||
|
|
||||||
return myrtlrect(membersTextLeft, membersTextTop, membersTextWidth, membersTextHeight);
|
return myrtlrect(membersTextLeft, membersTextTop, membersTextWidth, membersTextHeight);
|
||||||
|
@ -745,7 +744,10 @@ void TopBarWidget::updateOnlineDisplay() {
|
||||||
QString text;
|
QString text;
|
||||||
const auto now = unixtime();
|
const auto now = unixtime();
|
||||||
bool titlePeerTextOnline = false;
|
bool titlePeerTextOnline = false;
|
||||||
if (const auto user = _activeChat.peer()->asUser()) {
|
if (Auth().supportMode()
|
||||||
|
&& Support::IsOccupiedBySomeone(_activeChat.history())) {
|
||||||
|
text = Support::ChatOccupiedString();
|
||||||
|
} else if (const auto user = _activeChat.peer()->asUser()) {
|
||||||
text = Data::OnlineText(user, now);
|
text = Data::OnlineText(user, now);
|
||||||
titlePeerTextOnline = Data::OnlineTextActive(user, now);
|
titlePeerTextOnline = Data::OnlineTextActive(user, now);
|
||||||
} else if (const auto chat = _activeChat.peer()->asChat()) {
|
} else if (const auto chat = _activeChat.peer()->asChat()) {
|
||||||
|
@ -753,7 +755,7 @@ void TopBarWidget::updateOnlineDisplay() {
|
||||||
text = lang(lng_chat_status_unaccessible);
|
text = lang(lng_chat_status_unaccessible);
|
||||||
} else if (chat->participants.empty()) {
|
} else if (chat->participants.empty()) {
|
||||||
if (!_titlePeerText.isEmpty()) {
|
if (!_titlePeerText.isEmpty()) {
|
||||||
text = _titlePeerText;
|
text = _titlePeerText.originalText();
|
||||||
} else if (chat->count <= 0) {
|
} else if (chat->count <= 0) {
|
||||||
text = lang(lng_group_status);
|
text = lang(lng_group_status);
|
||||||
} else {
|
} else {
|
||||||
|
@ -810,10 +812,9 @@ void TopBarWidget::updateOnlineDisplay() {
|
||||||
text = lang(channel->isMegagroup() ? lng_group_status : lng_channel_status);
|
text = lang(channel->isMegagroup() ? lng_group_status : lng_channel_status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_titlePeerText != text) {
|
if (_titlePeerText.originalText() != text) {
|
||||||
_titlePeerText = text;
|
_titlePeerText.setText(st::dialogsTextStyle, text);
|
||||||
_titlePeerTextOnline = titlePeerTextOnline;
|
_titlePeerTextOnline = titlePeerTextOnline;
|
||||||
_titlePeerTextWidth = st::dialogsTextFont->width(_titlePeerText);
|
|
||||||
updateMembersShowArea();
|
updateMembersShowArea();
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,9 +136,8 @@ private:
|
||||||
object_ptr<TWidget> _membersShowArea = { nullptr };
|
object_ptr<TWidget> _membersShowArea = { nullptr };
|
||||||
rpl::event_stream<bool> _membersShowAreaActive;
|
rpl::event_stream<bool> _membersShowAreaActive;
|
||||||
|
|
||||||
QString _titlePeerText;
|
Text _titlePeerText;
|
||||||
bool _titlePeerTextOnline = false;
|
bool _titlePeerTextOnline = false;
|
||||||
int _titlePeerTextWidth = 0;
|
|
||||||
int _leftTaken = 0;
|
int _leftTaken = 0;
|
||||||
int _rightTaken = 0;
|
int _rightTaken = 0;
|
||||||
bool _animatingMode = false;
|
bool _animatingMode = false;
|
||||||
|
|
|
@ -3840,13 +3840,14 @@ void MainWidget::updateOnline(bool gotOtherOffline) {
|
||||||
void MainWidget::saveDraftToCloud() {
|
void MainWidget::saveDraftToCloud() {
|
||||||
_history->saveFieldToHistoryLocalDraft();
|
_history->saveFieldToHistoryLocalDraft();
|
||||||
|
|
||||||
auto peer = _history->peer();
|
const auto peer = _history->peer();
|
||||||
if (auto history = App::historyLoaded(peer)) {
|
if (const auto history = App::historyLoaded(peer)) {
|
||||||
writeDrafts(history);
|
writeDrafts(history);
|
||||||
|
|
||||||
auto localDraft = history->localDraft();
|
const auto localDraft = history->localDraft();
|
||||||
auto cloudDraft = history->cloudDraft();
|
const auto cloudDraft = history->cloudDraft();
|
||||||
if (!Data::draftsAreEqual(localDraft, cloudDraft)) {
|
if (!Data::draftsAreEqual(localDraft, cloudDraft)
|
||||||
|
&& !Auth().supportMode()) {
|
||||||
Auth().api().saveDraftToCloudDelayed(history);
|
Auth().api().saveDraftToCloudDelayed(history);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3859,17 +3860,27 @@ void MainWidget::applyCloudDraft(History *history) {
|
||||||
void MainWidget::writeDrafts(History *history) {
|
void MainWidget::writeDrafts(History *history) {
|
||||||
Local::MessageDraft storedLocalDraft, storedEditDraft;
|
Local::MessageDraft storedLocalDraft, storedEditDraft;
|
||||||
MessageCursor localCursor, editCursor;
|
MessageCursor localCursor, editCursor;
|
||||||
if (auto localDraft = history->localDraft()) {
|
if (const auto localDraft = history->localDraft()) {
|
||||||
if (!Data::draftsAreEqual(localDraft, history->cloudDraft())) {
|
if (Auth().supportMode()
|
||||||
storedLocalDraft = Local::MessageDraft(localDraft->msgId, localDraft->textWithTags, localDraft->previewCancelled);
|
|| !Data::draftsAreEqual(localDraft, history->cloudDraft())) {
|
||||||
|
storedLocalDraft = Local::MessageDraft(
|
||||||
|
localDraft->msgId,
|
||||||
|
localDraft->textWithTags,
|
||||||
|
localDraft->previewCancelled);
|
||||||
localCursor = localDraft->cursor;
|
localCursor = localDraft->cursor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (auto editDraft = history->editDraft()) {
|
if (const auto editDraft = history->editDraft()) {
|
||||||
storedEditDraft = Local::MessageDraft(editDraft->msgId, editDraft->textWithTags, editDraft->previewCancelled);
|
storedEditDraft = Local::MessageDraft(
|
||||||
|
editDraft->msgId,
|
||||||
|
editDraft->textWithTags,
|
||||||
|
editDraft->previewCancelled);
|
||||||
editCursor = editDraft->cursor;
|
editCursor = editDraft->cursor;
|
||||||
}
|
}
|
||||||
Local::writeDrafts(history->peer->id, storedLocalDraft, storedEditDraft);
|
Local::writeDrafts(
|
||||||
|
history->peer->id,
|
||||||
|
storedLocalDraft,
|
||||||
|
storedEditDraft);
|
||||||
Local::writeDraftCursors(history->peer->id, localCursor, editCursor);
|
Local::writeDraftCursors(history->peer->id, localCursor, editCursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,33 +39,34 @@ struct PeerUpdate {
|
||||||
RestrictionReasonChanged = (1 << 8),
|
RestrictionReasonChanged = (1 << 8),
|
||||||
UnreadViewChanged = (1 << 9),
|
UnreadViewChanged = (1 << 9),
|
||||||
PinnedMessageChanged = (1 << 10),
|
PinnedMessageChanged = (1 << 10),
|
||||||
|
OccupiedChanged = (1 << 11),
|
||||||
|
|
||||||
// For chats and channels
|
// For chats and channels
|
||||||
InviteLinkChanged = (1 << 11),
|
InviteLinkChanged = (1 << 12),
|
||||||
MembersChanged = (1 << 12),
|
MembersChanged = (1 << 13),
|
||||||
AdminsChanged = (1 << 13),
|
AdminsChanged = (1 << 14),
|
||||||
BannedUsersChanged = (1 << 14),
|
BannedUsersChanged = (1 << 15),
|
||||||
UnreadMentionsChanged = (1 << 15),
|
UnreadMentionsChanged = (1 << 16),
|
||||||
|
|
||||||
// For users
|
// For users
|
||||||
UserCanShareContact = (1 << 16),
|
UserCanShareContact = (1 << 17),
|
||||||
UserIsContact = (1 << 17),
|
UserIsContact = (1 << 18),
|
||||||
UserPhoneChanged = (1 << 18),
|
UserPhoneChanged = (1 << 19),
|
||||||
UserIsBlocked = (1 << 19),
|
UserIsBlocked = (1 << 20),
|
||||||
BotCommandsChanged = (1 << 20),
|
BotCommandsChanged = (1 << 21),
|
||||||
UserOnlineChanged = (1 << 21),
|
UserOnlineChanged = (1 << 22),
|
||||||
BotCanAddToGroups = (1 << 22),
|
BotCanAddToGroups = (1 << 23),
|
||||||
UserCommonChatsChanged = (1 << 23),
|
UserCommonChatsChanged = (1 << 24),
|
||||||
UserHasCalls = (1 << 24),
|
UserHasCalls = (1 << 25),
|
||||||
|
|
||||||
// For chats
|
// For chats
|
||||||
ChatCanEdit = (1 << 16),
|
ChatCanEdit = (1 << 17),
|
||||||
|
|
||||||
// For channels
|
// For channels
|
||||||
ChannelAmIn = (1 << 16),
|
ChannelAmIn = (1 << 17),
|
||||||
ChannelRightsChanged = (1 << 17),
|
ChannelRightsChanged = (1 << 18),
|
||||||
ChannelStickersChanged = (1 << 18),
|
ChannelStickersChanged = (1 << 19),
|
||||||
ChannelPromotedChanged = (1 << 19),
|
ChannelPromotedChanged = (1 << 20),
|
||||||
};
|
};
|
||||||
using Flags = base::flags<Flag>;
|
using Flags = base::flags<Flag>;
|
||||||
friend inline constexpr auto is_flag_type(Flag) { return true; }
|
friend inline constexpr auto is_flag_type(Flag) { return true; }
|
||||||
|
|
|
@ -328,11 +328,11 @@ Autocomplete::Autocomplete(QWidget *parent, not_null<AuthSession*> session)
|
||||||
}
|
}
|
||||||
|
|
||||||
void Autocomplete::activate(not_null<Ui::InputField*> field) {
|
void Autocomplete::activate(not_null<Ui::InputField*> field) {
|
||||||
if (Auth().settings().supportTemplatesAutocomplete()) {
|
if (_session->settings().supportTemplatesAutocomplete()) {
|
||||||
_activate();
|
_activate();
|
||||||
} else {
|
} else {
|
||||||
const auto templates = Auth().supportTemplates();
|
const auto &templates = _session->supportTemplates();
|
||||||
const auto max = templates->maxKeyLength();
|
const auto max = templates.maxKeyLength();
|
||||||
auto cursor = field->textCursor();
|
auto cursor = field->textCursor();
|
||||||
const auto position = cursor.position();
|
const auto position = cursor.position();
|
||||||
const auto anchor = cursor.anchor();
|
const auto anchor = cursor.anchor();
|
||||||
|
@ -344,8 +344,8 @@ void Autocomplete::activate(not_null<Ui::InputField*> field) {
|
||||||
std::max(position - max, 0),
|
std::max(position - max, 0),
|
||||||
position);
|
position);
|
||||||
const auto result = (position != anchor)
|
const auto result = (position != anchor)
|
||||||
? templates->matchExact(text.text)
|
? templates.matchExact(text.text)
|
||||||
: templates->matchFromEnd(text.text);
|
: templates.matchFromEnd(text.text);
|
||||||
if (result) {
|
if (result) {
|
||||||
const auto till = std::max(position, anchor);
|
const auto till = std::max(position, anchor);
|
||||||
const auto from = till - result->key.size();
|
const auto from = till - result->key.size();
|
||||||
|
@ -410,7 +410,7 @@ void Autocomplete::setupContent() {
|
||||||
|
|
||||||
const auto refresh = [=] {
|
const auto refresh = [=] {
|
||||||
inner->showRows(
|
inner->showRows(
|
||||||
_session->supportTemplates()->query(input->getLastText()));
|
_session->supportTemplates().query(input->getLastText()));
|
||||||
scroll->scrollToY(0);
|
scroll->scrollToY(0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,220 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#include "support/support_helper.h"
|
||||||
|
|
||||||
|
#include "dialogs/dialogs_key.h"
|
||||||
|
#include "data/data_drafts.h"
|
||||||
|
#include "history/history.h"
|
||||||
|
#include "window/window_controller.h"
|
||||||
|
#include "auth_session.h"
|
||||||
|
#include "observer_peer.h"
|
||||||
|
#include "apiwrap.h"
|
||||||
|
|
||||||
|
namespace Support {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr auto kOccupyFor = TimeId(60);
|
||||||
|
constexpr auto kReoccupyEach = 30 * TimeMs(1000);
|
||||||
|
|
||||||
|
uint32 OccupationTag() {
|
||||||
|
return uint32(Sandbox::UserTag() & 0xFFFFFFFFU);
|
||||||
|
}
|
||||||
|
|
||||||
|
Data::Draft OccupiedDraft() {
|
||||||
|
const auto now = unixtime(), till = now + kOccupyFor;
|
||||||
|
return {
|
||||||
|
TextWithTags{ "t:"
|
||||||
|
+ QString::number(till)
|
||||||
|
+ ";u:"
|
||||||
|
+ QString::number(OccupationTag()) },
|
||||||
|
MsgId(0),
|
||||||
|
MessageCursor(),
|
||||||
|
false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 ParseOccupationTag(History *history) {
|
||||||
|
if (!history) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const auto draft = history->cloudDraft();
|
||||||
|
if (!draft) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const auto &text = draft->textWithTags.text;
|
||||||
|
#ifndef OS_MAC_OLD
|
||||||
|
const auto parts = text.splitRef(';');
|
||||||
|
#else // OS_MAC_OLD
|
||||||
|
const auto parts = text.split(';');
|
||||||
|
#endif // OS_MAC_OLD
|
||||||
|
auto valid = false;
|
||||||
|
auto result = uint32();
|
||||||
|
for (const auto &part : parts) {
|
||||||
|
if (part.startsWith(qstr("t:"))) {
|
||||||
|
if (part.mid(2).toInt() >= unixtime()) {
|
||||||
|
valid = true;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else if (part.startsWith(qstr("u:"))) {
|
||||||
|
result = part.mid(2).toUInt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return valid ? result : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeId OccupiedBySomeoneTill(History *history) {
|
||||||
|
if (!history) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const auto draft = history->cloudDraft();
|
||||||
|
if (!draft) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const auto &text = draft->textWithTags.text;
|
||||||
|
#ifndef OS_MAC_OLD
|
||||||
|
const auto parts = text.splitRef(';');
|
||||||
|
#else // OS_MAC_OLD
|
||||||
|
const auto parts = text.split(';');
|
||||||
|
#endif // OS_MAC_OLD
|
||||||
|
auto valid = false;
|
||||||
|
auto result = TimeId();
|
||||||
|
for (const auto &part : parts) {
|
||||||
|
if (part.startsWith(qstr("t:"))) {
|
||||||
|
if (part.mid(2).toInt() >= unixtime()) {
|
||||||
|
result = part.mid(2).toInt();
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else if (part.startsWith(qstr("u:"))) {
|
||||||
|
if (part.mid(2).toUInt() != OccupationTag()) {
|
||||||
|
valid = true;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return valid ? result : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
Helper::Helper(not_null<AuthSession*> session)
|
||||||
|
: _session(session)
|
||||||
|
, _templates(_session)
|
||||||
|
, _reoccupyTimer([=] { reoccupy(); })
|
||||||
|
, _checkOccupiedTimer([=] { checkOccupiedChats(); }) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Helper::registerWindow(not_null<Window::Controller*> controller) {
|
||||||
|
controller->activeChatValue(
|
||||||
|
) | rpl::map([](Dialogs::Key key) {
|
||||||
|
return key.history();
|
||||||
|
}) | rpl::distinct_until_changed(
|
||||||
|
) | rpl::start_with_next([=](History *history) {
|
||||||
|
updateOccupiedHistory(controller, history);
|
||||||
|
}, controller->lifetime());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Helper::cloudDraftChanged(not_null<History*> history) {
|
||||||
|
chatOccupiedUpdated(history);
|
||||||
|
if (history != _occupiedHistory) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!IsOccupiedByMe(_occupiedHistory)) {
|
||||||
|
occupyInDraft();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Helper::chatOccupiedUpdated(not_null<History*> history) {
|
||||||
|
if (const auto till = OccupiedBySomeoneTill(history)) {
|
||||||
|
_occupiedChats[history] = till + 2;
|
||||||
|
Notify::peerUpdatedDelayed(
|
||||||
|
history->peer,
|
||||||
|
Notify::PeerUpdate::Flag::OccupiedChanged);
|
||||||
|
checkOccupiedChats();
|
||||||
|
} else if (_occupiedChats.take(history)) {
|
||||||
|
Notify::peerUpdatedDelayed(
|
||||||
|
history->peer,
|
||||||
|
Notify::PeerUpdate::Flag::OccupiedChanged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Helper::checkOccupiedChats() {
|
||||||
|
const auto now = unixtime();
|
||||||
|
while (!_occupiedChats.empty()) {
|
||||||
|
const auto nearest = ranges::min_element(
|
||||||
|
_occupiedChats,
|
||||||
|
std::less<>(),
|
||||||
|
[](const auto &pair) { return pair.second; });
|
||||||
|
if (nearest->second <= now) {
|
||||||
|
const auto history = nearest->first;
|
||||||
|
_occupiedChats.erase(nearest);
|
||||||
|
Notify::peerUpdatedDelayed(
|
||||||
|
history->peer,
|
||||||
|
Notify::PeerUpdate::Flag::OccupiedChanged);
|
||||||
|
} else {
|
||||||
|
_checkOccupiedTimer.callOnce(
|
||||||
|
(nearest->second - now) * TimeMs(1000));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_checkOccupiedTimer.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Helper::updateOccupiedHistory(
|
||||||
|
not_null<Window::Controller*> controller,
|
||||||
|
History *history) {
|
||||||
|
if (IsOccupiedByMe(_occupiedHistory)) {
|
||||||
|
_occupiedHistory->clearCloudDraft();
|
||||||
|
_session->api().saveDraftToCloudDelayed(_occupiedHistory);
|
||||||
|
}
|
||||||
|
_occupiedHistory = history;
|
||||||
|
occupyInDraft();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Helper::occupyInDraft() {
|
||||||
|
if (_occupiedHistory && !IsOccupiedBySomeone(_occupiedHistory)) {
|
||||||
|
const auto draft = OccupiedDraft();
|
||||||
|
_occupiedHistory->createCloudDraft(&draft);
|
||||||
|
_session->api().saveDraftToCloudDelayed(_occupiedHistory);
|
||||||
|
_reoccupyTimer.callEach(kReoccupyEach);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Helper::reoccupy() {
|
||||||
|
if (IsOccupiedByMe(_occupiedHistory)) {
|
||||||
|
const auto draft = OccupiedDraft();
|
||||||
|
_occupiedHistory->createCloudDraft(&draft);
|
||||||
|
_session->api().saveDraftToCloudDelayed(_occupiedHistory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Templates &Helper::templates() {
|
||||||
|
return _templates;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsOccupiedByMe(History *history) {
|
||||||
|
if (const auto tag = ParseOccupationTag(history)) {
|
||||||
|
return (tag == OccupationTag());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsOccupiedBySomeone(History *history) {
|
||||||
|
if (const auto tag = ParseOccupationTag(history)) {
|
||||||
|
return (tag != OccupationTag());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ChatOccupiedString() {
|
||||||
|
return QString::fromUtf8("\xe2\x9c\x8b\xef\xb8\x8f chat taken");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Support
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "base/timer.h"
|
||||||
|
#include "support/support_templates.h"
|
||||||
|
|
||||||
|
class AuthSession;
|
||||||
|
|
||||||
|
namespace Window {
|
||||||
|
class Controller;
|
||||||
|
} // namespace Window
|
||||||
|
|
||||||
|
namespace Support {
|
||||||
|
|
||||||
|
class Helper {
|
||||||
|
public:
|
||||||
|
explicit Helper(not_null<AuthSession*> session);
|
||||||
|
|
||||||
|
void registerWindow(not_null<Window::Controller*> controller);
|
||||||
|
void cloudDraftChanged(not_null<History*> history);
|
||||||
|
|
||||||
|
void chatOccupiedUpdated(not_null<History*> history);
|
||||||
|
|
||||||
|
Templates &templates();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void checkOccupiedChats();
|
||||||
|
void updateOccupiedHistory(
|
||||||
|
not_null<Window::Controller*> controller,
|
||||||
|
History *history);
|
||||||
|
void occupyInDraft();
|
||||||
|
void reoccupy();
|
||||||
|
|
||||||
|
not_null<AuthSession*> _session;
|
||||||
|
Templates _templates;
|
||||||
|
|
||||||
|
History *_occupiedHistory = nullptr;
|
||||||
|
base::Timer _reoccupyTimer;
|
||||||
|
base::Timer _checkOccupiedTimer;
|
||||||
|
base::flat_map<not_null<History*>, TimeId> _occupiedChats;
|
||||||
|
|
||||||
|
rpl::lifetime _lifetime;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
bool IsOccupiedByMe(History *history);
|
||||||
|
bool IsOccupiedBySomeone(History *history);
|
||||||
|
QString ChatOccupiedString();
|
||||||
|
|
||||||
|
} // namespace Support
|
|
@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "auth_session.h"
|
#include "auth_session.h"
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
|
#include "support/support_helper.h"
|
||||||
#include "styles/style_window.h"
|
#include "styles/style_window.h"
|
||||||
#include "styles/style_dialogs.h"
|
#include "styles/style_dialogs.h"
|
||||||
|
|
||||||
|
@ -50,6 +51,10 @@ Controller::Controller(not_null<MainWindow*> window)
|
||||||
startRoundVideo(item);
|
startRoundVideo(item);
|
||||||
}
|
}
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
|
if (Auth().supportMode()) {
|
||||||
|
Auth().supportHelper().registerWindow(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::setActiveChatEntry(Dialogs::RowDescriptor row) {
|
void Controller::setActiveChatEntry(Dialogs::RowDescriptor row) {
|
||||||
|
|
|
@ -214,13 +214,13 @@ void MainMenu::refreshMenu() {
|
||||||
|
|
||||||
const auto subscription = Ui::AttachAsChild(_menu, rpl::lifetime());
|
const auto subscription = Ui::AttachAsChild(_menu, rpl::lifetime());
|
||||||
_menu->addAction(qsl("Reload templates"), [=] {
|
_menu->addAction(qsl("Reload templates"), [=] {
|
||||||
*subscription = Auth().supportTemplates()->errors(
|
*subscription = Auth().supportTemplates().errors(
|
||||||
) | rpl::start_with_next([=](QStringList errors) {
|
) | rpl::start_with_next([=](QStringList errors) {
|
||||||
Ui::Toast::Show(errors.isEmpty()
|
Ui::Toast::Show(errors.isEmpty()
|
||||||
? "Templates reloaded!"
|
? "Templates reloaded!"
|
||||||
: ("Errors:\n\n" + errors.join("\n\n")));
|
: ("Errors:\n\n" + errors.join("\n\n")));
|
||||||
});
|
});
|
||||||
Auth().supportTemplates()->reload();
|
Auth().supportTemplates().reload();
|
||||||
}, &st::mainMenuReload, &st::mainMenuReloadOver);
|
}, &st::mainMenuReload, &st::mainMenuReloadOver);
|
||||||
}
|
}
|
||||||
_menu->addAction(lang(lng_menu_settings), [] {
|
_menu->addAction(lang(lng_menu_settings), [] {
|
||||||
|
|
|
@ -582,6 +582,8 @@
|
||||||
<(src_loc)/support/support_autocomplete.h
|
<(src_loc)/support/support_autocomplete.h
|
||||||
<(src_loc)/support/support_common.cpp
|
<(src_loc)/support/support_common.cpp
|
||||||
<(src_loc)/support/support_common.h
|
<(src_loc)/support/support_common.h
|
||||||
|
<(src_loc)/support/support_helper.cpp
|
||||||
|
<(src_loc)/support/support_helper.h
|
||||||
<(src_loc)/support/support_templates.cpp
|
<(src_loc)/support/support_templates.cpp
|
||||||
<(src_loc)/support/support_templates.h
|
<(src_loc)/support/support_templates.h
|
||||||
<(src_loc)/ui/effects/cross_animation.cpp
|
<(src_loc)/ui/effects/cross_animation.cpp
|
||||||
|
|
Loading…
Reference in New Issue