diff --git a/Telegram/Resources/lang.strings b/Telegram/Resources/lang.strings index 95efa2589b..7c3cd15cdb 100644 --- a/Telegram/Resources/lang.strings +++ b/Telegram/Resources/lang.strings @@ -542,6 +542,15 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_profile_migrate_feature4" = "— Notifications are muted by default"; "lng_profile_migrate_button" = "Upgrade to supergroup"; "lng_profile_migrate_sure" = "Are you sure you want to upgrade this group to supergroup? This action cannot be undone."; +"lng_profile_convert_button" = "Convert to supergroup"; +"lng_profile_convert_title" = "Convert to supergroup"; +"lng_profile_convert_about" = "In supergroups:"; +"lng_profile_convert_feature1" = "— New members can see full message history"; +"lng_profile_convert_feature2" = "— Messages are deleted for all members"; +"lng_profile_convert_feature3" = "— Members can edit their own messages"; +"lng_profile_convert_feature4" = "— Creator can set a public link for the group"; +"lng_profile_convert_warning" = "{bold_start}Note:{bold_end} This action can not be undone"; +"lng_profile_convert_confirm" = "Convert"; "lng_channel_comments_count" = "{count:_not_used_|# comment|# comments}"; "lng_channel_hide_comments" = "Hide comments"; diff --git a/Telegram/SourceFiles/boxes/addcontactbox.cpp b/Telegram/SourceFiles/boxes/addcontactbox.cpp index 7ba83729da..0d6f55d3af 100644 --- a/Telegram/SourceFiles/boxes/addcontactbox.cpp +++ b/Telegram/SourceFiles/boxes/addcontactbox.cpp @@ -1213,7 +1213,11 @@ void EditChannelBox::showAll() { _description.show(); _save.show(); _cancel.show(); - _publicLink.show(); + if (_channel->amCreator()) { + _publicLink.show(); + } else { + _publicLink.hide(); + } if (_channel->isMegagroup()) { _sign.hide(); } else { @@ -1260,7 +1264,9 @@ void EditChannelBox::updateMaxHeight() { if (!_channel->isMegagroup()) { h += st::newGroupPublicLinkPadding.top() + _sign.height() + st::newGroupPublicLinkPadding.bottom(); } - h += st::newGroupPublicLinkPadding.top() + _publicLink.height() + st::newGroupPublicLinkPadding.bottom(); + if (_channel->amCreator()) { + h += st::newGroupPublicLinkPadding.top() + _publicLink.height() + st::newGroupPublicLinkPadding.bottom(); + } h += st::boxPadding.bottom() + st::newGroupInfoPadding.bottom() + st::boxButtonPadding.top() + _save.height() + st::boxButtonPadding.bottom(); setMaxHeight(h); } diff --git a/Telegram/SourceFiles/boxes/confirmbox.cpp b/Telegram/SourceFiles/boxes/confirmbox.cpp index f7d3bfc64d..27eb480ed3 100644 --- a/Telegram/SourceFiles/boxes/confirmbox.cpp +++ b/Telegram/SourceFiles/boxes/confirmbox.cpp @@ -34,19 +34,19 @@ TextParseOptions _confirmBoxTextOptions = { Qt::LayoutDirectionAuto, // dir }; -ConfirmBox::ConfirmBox(const QString &text, const QString &doneText, const style::BoxButton &doneStyle, const QString &cancelText, const style::BoxButton &cancelStyle) : AbstractBox(st::boxWidth), -_informative(false), -_text(100), -_confirm(this, doneText.isEmpty() ? lang(lng_box_ok) : doneText, doneStyle), -_cancel(this, cancelText.isEmpty() ? lang(lng_cancel) : cancelText, cancelStyle) { +ConfirmBox::ConfirmBox(const QString &text, const QString &doneText, const style::BoxButton &doneStyle, const QString &cancelText, const style::BoxButton &cancelStyle) : AbstractBox(st::boxWidth) +, _informative(false) +, _text(100) +, _confirm(this, doneText.isEmpty() ? lang(lng_box_ok) : doneText, doneStyle) +, _cancel(this, cancelText.isEmpty() ? lang(lng_cancel) : cancelText, cancelStyle) { init(text); } -ConfirmBox::ConfirmBox(const QString &text, const QString &doneText, const style::BoxButton &doneStyle, bool informative) : AbstractBox(st::boxWidth), -_informative(true), -_text(100), -_confirm(this, doneText.isEmpty() ? lang(lng_box_ok) : doneText, doneStyle), -_cancel(this, QString(), st::cancelBoxButton) { +ConfirmBox::ConfirmBox(const QString &text, const QString &doneText, const style::BoxButton &doneStyle, bool informative) : AbstractBox(st::boxWidth) +, _informative(true) +, _text(100) +, _confirm(this, doneText.isEmpty() ? lang(lng_box_ok) : doneText, doneStyle) +, _cancel(this, QString(), st::cancelBoxButton) { init(text); } @@ -174,7 +174,8 @@ void ConfirmBox::resizeEvent(QResizeEvent *e) { _cancel.moveToRight(st::boxButtonPadding.right() + _confirm.width() + st::boxButtonPadding.left(), _confirm.y()); } -ConfirmLinkBox::ConfirmLinkBox(const QString &url) : ConfirmBox(lang(lng_open_this_link) + qsl("\n\n") + url, lang(lng_open_link)), _url(url) { +ConfirmLinkBox::ConfirmLinkBox(const QString &url) : ConfirmBox(lang(lng_open_this_link) + qsl("\n\n") + url, lang(lng_open_link)) +, _url(url) { connect(this, SIGNAL(confirmed()), this, SLOT(onOpenLink())); } @@ -279,3 +280,101 @@ void MaxInviteBox::resizeEvent(QResizeEvent *e) { _close.moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _close.height()); _invitationLink = myrtlrect(st::boxPadding.left(), st::boxPadding.top() + _textHeight + st::boxTextFont->height, width() - st::boxPadding.left() - st::boxPadding.right(), 2 * st::boxTextFont->height); } + +ConvertToSupergroupBox::ConvertToSupergroupBox(ChatData *chat) : AbstractBox(st::boxWideWidth) +, _chat(chat) +, _text(100) +, _note(100) +, _convert(this, lang(lng_profile_convert_confirm), st::defaultBoxButton) +, _cancel(this, lang(lng_cancel), st::cancelBoxButton) { + QStringList text; + text.push_back(lang(lng_profile_convert_feature1)); + text.push_back(lang(lng_profile_convert_feature2)); + text.push_back(lang(lng_profile_convert_feature3)); + text.push_back(lang(lng_profile_convert_feature4)); + + textstyleSet(&st::boxTextStyle); + _text.setText(st::boxTextFont, text.join('\n'), _confirmBoxTextOptions); + _note.setText(st::boxTextFont, lng_profile_convert_warning(lt_bold_start, textcmdStartSemibold(), lt_bold_end, textcmdStopSemibold()), _confirmBoxTextOptions); + _textWidth = st::boxWideWidth - st::boxPadding.left() - st::boxButtonPadding.right(); + _textHeight = _text.countHeight(_textWidth); + setMaxHeight(st::boxTitleHeight + _textHeight + st::boxPadding.bottom() + st::boxTextFont->height + st::boxButtonPadding.top() + _convert.height() + st::boxButtonPadding.bottom()); + textstyleRestore(); + + connect(&_convert, SIGNAL(clicked()), this, SLOT(onConvert())); + connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose())); + + prepare(); +} + +void ConvertToSupergroupBox::onConvert() { + MTP::send(MTPmessages_MigrateChat(_chat->inputChat), rpcDone(&ConvertToSupergroupBox::convertDone), rpcFail(&ConvertToSupergroupBox::convertFail)); +} + +void ConvertToSupergroupBox::convertDone(const MTPUpdates &updates) { + Ui::hideLayer(); + App::main()->sentUpdatesReceived(updates); + const QVector *v = 0; + switch (updates.type()) { + case mtpc_updates: v = &updates.c_updates().vchats.c_vector().v; break; + case mtpc_updatesCombined: v = &updates.c_updatesCombined().vchats.c_vector().v; break; + default: LOG(("API Error: unexpected update cons %1 (ConvertToSupergroupBox::convertDone)").arg(updates.type())); break; + } + + PeerData *peer = 0; + if (v && !v->isEmpty()) { + for (int32 i = 0, l = v->size(); i < l; ++i) { + if (v->at(i).type() == mtpc_channel) { + peer = App::channel(v->at(i).c_channel().vid.v); + Ui::showPeerHistory(peer, ShowAtUnreadMsgId); + QTimer::singleShot(ReloadChannelMembersTimeout, App::api(), SLOT(delayedRequestParticipantsCount())); + } + } + } + if (!peer) { + LOG(("API Error: channel not found in updates (ProfileInner::migrateDone)")); + } +} + +bool ConvertToSupergroupBox::convertFail(const RPCError &error) { + if (mtpIsFlood(error)) return false; + Ui::hideLayer(); + return true; +} + +void ConvertToSupergroupBox::hideAll() { + _convert.hide(); + _cancel.hide(); +} + +void ConvertToSupergroupBox::showAll() { + _convert.show(); + _cancel.show(); +} + +void ConvertToSupergroupBox::keyPressEvent(QKeyEvent *e) { + if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) { + onConvert(); + } else { + AbstractBox::keyPressEvent(e); + } +} + +void ConvertToSupergroupBox::paintEvent(QPaintEvent *e) { + Painter p(this); + if (paint(p)) return; + + paintTitle(p, lang(lng_profile_convert_title)); + + // draw box title / text + p.setPen(st::black); + textstyleSet(&st::boxTextStyle); + _text.drawLeft(p, st::boxPadding.left(), st::boxTitleHeight, _textWidth, width()); + _note.drawLeft(p, st::boxPadding.left(), st::boxTitleHeight + _textHeight + st::boxPadding.bottom(), _textWidth, width()); + textstyleRestore(); +} + +void ConvertToSupergroupBox::resizeEvent(QResizeEvent *e) { + _convert.moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _convert.height()); + _cancel.moveToRight(st::boxButtonPadding.right() + _convert.width() + st::boxButtonPadding.left(), _convert.y()); +} diff --git a/Telegram/SourceFiles/boxes/confirmbox.h b/Telegram/SourceFiles/boxes/confirmbox.h index 6cfd601991..05ed14212c 100644 --- a/Telegram/SourceFiles/boxes/confirmbox.h +++ b/Telegram/SourceFiles/boxes/confirmbox.h @@ -108,7 +108,7 @@ public: void mouseMoveEvent(QMouseEvent *e); void mousePressEvent(QMouseEvent *e); void leaveEvent(QEvent *e); - + protected: void hideAll(); @@ -133,3 +133,34 @@ private: anim::fvalue a_goodOpacity; Animation _a_good; }; + +class ConvertToSupergroupBox : public AbstractBox, public RPCSender { + Q_OBJECT + +public: + + ConvertToSupergroupBox(ChatData *chat); + void keyPressEvent(QKeyEvent *e); + void paintEvent(QPaintEvent *e); + void resizeEvent(QResizeEvent *e); + +public slots: + + void onConvert(); + +protected: + + void hideAll(); + void showAll(); + +private: + + void convertDone(const MTPUpdates &updates); + bool convertFail(const RPCError &error); + + ChatData *_chat; + Text _text, _note; + int32 _textWidth, _textHeight; + + BoxButton _convert, _cancel; +}; \ No newline at end of file diff --git a/Telegram/SourceFiles/gui/text.cpp b/Telegram/SourceFiles/gui/text.cpp index 591a6d782f..881aeed1c6 100644 --- a/Telegram/SourceFiles/gui/text.cpp +++ b/Telegram/SourceFiles/gui/text.cpp @@ -212,6 +212,18 @@ QString textcmdStopColor() { return result.append(TextCommand).append(QChar(TextCommandNoColor)).append(TextCommand); } +QString textcmdStartSemibold() { + QString result; + result.reserve(3); + return result.append(TextCommand).append(QChar(TextCommandSemibold)).append(TextCommand); +} + +QString textcmdStopSemibold() { + QString result; + result.reserve(3); + return result.append(TextCommand).append(QChar(TextCommandNoSemibold)).append(TextCommand); +} + const QChar *textSkipCommand(const QChar *from, const QChar *end, bool canLink) { const QChar *result = from + 1; if (*from != TextCommand || result >= end) return from; @@ -223,6 +235,8 @@ const QChar *textSkipCommand(const QChar *from, const QChar *end, bool canLink) switch (cmd) { case TextCommandBold: case TextCommandNoBold: + case TextCommandSemibold: + case TextCommandNoSemibold: case TextCommandItalic: case TextCommandNoItalic: case TextCommandUnderline: @@ -498,6 +512,20 @@ public: } break; + case TextCommandSemibold: + if (!(flags & TextBlockFSemibold)) { + createBlock(); + flags |= TextBlockFSemibold; + } + break; + + case TextCommandNoSemibold: + if (flags & TextBlockFSemibold) { + createBlock(); + flags &= ~TextBlockFSemibold; + } + break; + case TextCommandItalic: if (!(flags & TextBlockFItalic)) { createBlock(); diff --git a/Telegram/SourceFiles/gui/text.h b/Telegram/SourceFiles/gui/text.h index 944d83fff9..d78f20cf57 100644 --- a/Telegram/SourceFiles/gui/text.h +++ b/Telegram/SourceFiles/gui/text.h @@ -564,11 +564,13 @@ enum TextCommands { TextCommandNoItalic = 0x04, TextCommandUnderline = 0x05, TextCommandNoUnderline = 0x06, - TextCommandLinkIndex = 0x07, // 0 - NoLink - TextCommandLinkText = 0x08, - TextCommandColor = 0x09, - TextCommandNoColor = 0x0A, - TextCommandSkipBlock = 0x0B, + TextCommandSemibold = 0x07, + TextCommandNoSemibold = 0x08, + TextCommandLinkIndex = 0x09, // 0 - NoLink + TextCommandLinkText = 0x0A, + TextCommandColor = 0x0B, + TextCommandNoColor = 0x0C, + TextCommandSkipBlock = 0x0D, TextCommandLangTag = 0x20, }; @@ -747,6 +749,8 @@ QString textcmdLink(ushort lnkIndex, const QString &text); QString textcmdLink(const QString &url, const QString &text); QString textcmdStartColor(const style::color &color); QString textcmdStopColor(); +QString textcmdStartSemibold(); +QString textcmdStopSemibold(); const QChar *textSkipCommand(const QChar *from, const QChar *end, bool canLink = true); inline bool chIsSpace(QChar ch, bool rich = false) { diff --git a/Telegram/SourceFiles/profilewidget.cpp b/Telegram/SourceFiles/profilewidget.cpp index 859dd74412..16ed4b4c04 100644 --- a/Telegram/SourceFiles/profilewidget.cpp +++ b/Telegram/SourceFiles/profilewidget.cpp @@ -85,6 +85,7 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, PeerData // actions , _searchInPeer(this, lang(lng_profile_search_messages)) +, _convertToSupergroup(this, lang(lng_profile_convert_button)) , _clearHistory(this, lang(lng_profile_clear_history)) , _deleteConversation(this, lang(_peer->isUser() ? lng_profile_delete_conversation : (_peer->isChat() ? lng_profile_clear_and_exit : (_peer->isMegagroup() ? lng_profile_leave_group : lng_profile_leave_channel)))) , _wasBlocked(_peerUser ? _peerUser->blocked : UserBlockUnknown) @@ -218,6 +219,7 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, PeerData // actions connect(&_searchInPeer, SIGNAL(clicked()), this, SLOT(onSearchInPeer())); + connect(&_convertToSupergroup, SIGNAL(clicked()), this, SLOT(onConvertToSupergroup())); connect(&_clearHistory, SIGNAL(clicked()), this, SLOT(onClearHistory())); connect(&_deleteConversation, SIGNAL(clicked()), this, SLOT(onDeleteConversation())); connect(&_blockUser, SIGNAL(clicked()), this, SLOT(onBlockUser())); @@ -245,6 +247,10 @@ void ProfileInner::onSearchInPeer() { App::main()->searchInPeer(_peer); } +void ProfileInner::onConvertToSupergroup() { + Ui::showLayer(new ConvertToSupergroupBox(_peerChat)); +} + void ProfileInner::onEnableNotifications() { App::main()->updateNotifySetting(_peer, _enableNotifications.checked() ? NotifySettingSetNotify : NotifySettingSetMuted); } @@ -949,6 +955,9 @@ void ProfileInner::paintEvent(QPaintEvent *e) { top += st::profileHeaderSkip; top += _searchInPeer.height() + st::setLittleSkip; + if (_peerChat && _amCreator && !_showMigrate) { + top += _convertToSupergroup.height() + st::setLittleSkip; + } if (_peerUser || _peerChat) { top += _clearHistory.height() + st::setLittleSkip; } @@ -1429,6 +1438,9 @@ void ProfileInner::resizeEvent(QResizeEvent *e) { // actions top += st::profileHeaderSkip; _searchInPeer.move(_left, top); top += _searchInPeer.height() + st::setLittleSkip; + if (_peerChat && _amCreator && !_showMigrate) { + _convertToSupergroup.move(_left, top); top += _convertToSupergroup.height() + st::setLittleSkip; + } if (_peerUser || _peerChat) { _clearHistory.move(_left, top); top += _clearHistory.height() + st::setLittleSkip; } @@ -1585,6 +1597,11 @@ void ProfileInner::allowDecreaseHeight(int32 decreaseBy) { void ProfileInner::showAll() { _searchInPeer.show(); + if (_peerChat && _amCreator && !_showMigrate) { + _convertToSupergroup.show(); + } else { + _convertToSupergroup.hide(); + } if (_peerUser || _peerChat) { _clearHistory.show(); } else { diff --git a/Telegram/SourceFiles/profilewidget.h b/Telegram/SourceFiles/profilewidget.h index f512b442ad..4527d483d2 100644 --- a/Telegram/SourceFiles/profilewidget.h +++ b/Telegram/SourceFiles/profilewidget.h @@ -78,6 +78,7 @@ public slots: void onInviteToGroup(); void onSendMessage(); void onSearchInPeer(); + void onConvertToSupergroup(); void onEnableNotifications(); void onClearHistory(); @@ -184,7 +185,7 @@ private: QString overviewLinkText(int32 type, int32 count); // actions - LinkButton _searchInPeer, _clearHistory, _deleteConversation; + LinkButton _searchInPeer, _convertToSupergroup, _clearHistory, _deleteConversation; UserBlockedStatus _wasBlocked; mtpRequestId _blockRequest; LinkButton _blockUser, _deleteChannel;