diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index e91fc9eee..0bbc28ad9 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -780,6 +780,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_info_username_label" = "Username"; "lng_info_bio_label" = "Bio"; "lng_info_link_label" = "Link"; +"lng_info_location_label" = "Location"; "lng_info_about_label" = "About"; "lng_info_user_title" = "User Info"; "lng_info_bot_title" = "Bot Info"; @@ -844,6 +845,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_manage_peer_group_type" = "Group type"; "lng_manage_peer_channel_type" = "Channel type"; +"lng_manage_peer_link_type" = "Link type"; +"lng_manage_peer_link_permanent" = "Permanent link"; +"lng_manage_peer_link_invite" = "Invite link"; "lng_manage_private_group_title" = "Private"; "lng_manage_public_group_title" = "Public"; "lng_manage_private_peer_title" = "Private"; @@ -924,6 +928,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_create_public_group_about" = "Anyone can find the group in search and join, chat history is available to everybody"; "lng_create_private_group_title" = "Private Group"; "lng_create_private_group_about" = "People can only join if they were invited or have an invite link"; +"lng_create_permanent_link_title" = "Permanent link"; +"lng_create_invite_link_title" = "Invite link"; +"lng_create_invite_link_about" = "People can join if they were invited, have an invite link, or from \"Groups nearby\""; + "lng_create_group_skip" = "Skip"; "lng_create_channel_link_about" = "You can use a-z, 0-9 and underscores.\nMinimum length is 5 characters."; @@ -1048,6 +1056,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_channels_too_much_public_revoke_confirm_channel" = "Are you sure you want to revoke the link {link}?\n\nThe channel «{group}» will become private."; "lng_channels_too_much_public_revoke" = "Revoke"; "lng_channels_too_much_public_other" = "Sorry, the target user has too many public groups or channels already. Please ask them to make one of their existing groups or channels private first."; +"lng_channels_too_much_located_other" = "Sorry, the target user has too many location-based groups already. Please ask them to delete or transfer one of their existing ones first."; "lng_group_invite_bad_link" = "This invite link is broken or has expired."; "lng_group_invite_join" = "Join"; diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 66a54f1b7..5bb6dc850 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -691,11 +691,11 @@ QString ApiWrap::exportDirectMessageLink(not_null item) { const auto itemId = item->fullId(); const auto channel = item->history()->peer->asChannel(); const auto fallback = [&] { - const auto base = channel->isPublic() + const auto base = channel->hasUsername() ? channel->username : "c/" + QString::number(channel->bareId()); const auto query = base + '/' + QString::number(item->id); - if (channel->isPublic() && !channel->isMegagroup()) { + if (channel->hasUsername() && !channel->isMegagroup()) { if (const auto media = item->media()) { if (const auto document = media->document()) { if (document->isVideoMessage()) { diff --git a/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp index 63fd6732d..2150b340a 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp @@ -537,6 +537,8 @@ void EditAdminBox::sendTransferRequestFrom( const auto problem = [&] { if (type == qstr("CHANNELS_ADMIN_PUBLIC_TOO_MUCH")) { return tr::lng_channels_too_much_public_other(tr::now); + } else if (type == qstr("CHANNELS_ADMIN_LOCATED_TOO_MUCH")) { + return tr::lng_channels_too_much_located_other(tr::now); } else if (type == qstr("ADMINS_TOO_MUCH")) { return (channel->isBroadcast() ? tr::lng_error_admin_limit_channel diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp index d1b38e093..9e04bbea2 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp @@ -240,6 +240,7 @@ private: std::optional _privacySavedValue; std::optional _linkedChatSavedValue; ChannelData *_linkedChatOriginalValue = nullptr; + bool _channelHasLocationOriginalValue = false; std::optional _historyVisibilitySavedValue; std::optional _usernameSavedValue; std::optional _signaturesSavedValue; @@ -489,7 +490,8 @@ void Controller::refreshHistoryVisibility(anim::type animated) { return; } _controls.historyVisibilityWrap->toggle( - (_privacySavedValue != Privacy::Public + (_privacySavedValue != Privacy::HasUsername + && !_channelHasLocationOriginalValue && (!_linkedChatSavedValue || !*_linkedChatSavedValue)), animated); }; @@ -506,6 +508,7 @@ void Controller::showEditPeerTypeBox( Ui::show( Box( _peer, + _channelHasLocationOriginalValue, boxCallback, _privacySavedValue, _usernameSavedValue, @@ -569,26 +572,34 @@ void Controller::fillPrivacyTypeButton() { Expects(_controls.buttonsLayout != nullptr); // Create Privacy Button. + const auto hasLocation = _peer->isChannel() + && _peer->asChannel()->hasLocation(); _privacySavedValue = (_peer->isChannel() - && _peer->asChannel()->isPublic()) - ? Privacy::Public - : Privacy::Private; + && _peer->asChannel()->hasUsername()) + ? Privacy::HasUsername + : Privacy::NoUsername; const auto isGroup = (_peer->isChat() || _peer->isMegagroup()); AddButtonWithText( _controls.buttonsLayout, - (isGroup + (hasLocation + ? tr::lng_manage_peer_link_type + : isGroup ? tr::lng_manage_peer_group_type : tr::lng_manage_peer_channel_type)(), _privacyTypeUpdates.events( ) | rpl::map([=](Privacy flag) { - return (Privacy::Public == flag - ? (isGroup + return (flag == Privacy::HasUsername) + ? (hasLocation + ? tr::lng_manage_peer_link_permanent + : isGroup ? tr::lng_manage_public_group_title - : tr::lng_manage_public_peer_title) - : (isGroup + : tr::lng_manage_public_peer_title)() + : (hasLocation + ? tr::lng_manage_peer_link_invite + : isGroup ? tr::lng_manage_private_group_title - : tr::lng_manage_private_peer_title))(); + : tr::lng_manage_private_peer_title)(); }) | rpl::flatten_latest(), [=] { showEditPeerTypeBox(); }); @@ -640,9 +651,7 @@ void Controller::fillInviteLinkButton() { Expects(_controls.buttonsLayout != nullptr); const auto buttonCallback = [=] { - Ui::show( - Box(_peer), - LayerOption::KeepOther); + Ui::show(Box(_peer), LayerOption::KeepOther); }; AddButtonWithText( @@ -685,6 +694,7 @@ void Controller::fillHistoryVisibilityButton() { _historyVisibilitySavedValue = (!channel || channel->hiddenPreHistory()) ? HistoryVisibility::Hidden : HistoryVisibility::Visible; + _channelHasLocationOriginalValue = channel && channel->hasLocation(); const auto updateHistoryVisibility = std::make_shared>(); @@ -945,7 +955,7 @@ std::optional Controller::validate() const { bool Controller::validateUsername(Saving &to) const { if (!_privacySavedValue) { return true; - } else if (_privacySavedValue != Privacy::Public) { + } else if (_privacySavedValue != Privacy::HasUsername) { to.username = QString(); return true; } @@ -994,7 +1004,8 @@ bool Controller::validateDescription(Saving &to) const { bool Controller::validateHistoryVisibility(Saving &to) const { if (!_controls.historyVisibilityWrap || !_controls.historyVisibilityWrap->toggled() - || (_privacySavedValue == Privacy::Public)) { + || _channelHasLocationOriginalValue + || (_privacySavedValue == Privacy::HasUsername)) { return true; } to.hiddenPreHistory diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_type_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_type_box.cpp index fed537541..c717f48a2 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_type_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_type_box.cpp @@ -51,6 +51,7 @@ public: Controller( not_null container, not_null peer, + bool useLocationPhrases, std::optional privacySavedValue, std::optional usernameSavedValue); @@ -129,10 +130,8 @@ private: void addRoundButton( not_null container, Privacy value, - const QString &groupText, - const QString &channelText, - rpl::producer groupAbout, - rpl::producer channelAbout); + const QString &text, + rpl::producer about); bool inviteLinkShown(); QString inviteLinkText(); @@ -141,6 +140,7 @@ private: std::optional _privacySavedValue; std::optional _usernameSavedValue; + bool _useLocationPhrases = false; bool _isGroup = false; bool _isInviteLink = false; bool _isAllowSave = false; @@ -158,11 +158,13 @@ private: Controller::Controller( not_null container, not_null peer, + bool useLocationPhrases, std::optional privacySavedValue, std::optional usernameSavedValue) : _peer(peer) , _privacySavedValue(privacySavedValue) , _usernameSavedValue(usernameSavedValue) +, _useLocationPhrases(useLocationPhrases) , _isGroup(_peer->isChat() || _peer->isMegagroup()) , _isInviteLink(!_privacySavedValue.has_value() && !_usernameSavedValue.has_value()) @@ -189,7 +191,7 @@ void Controller::createContent() { _wrap->add(createInviteLinkEdit()); _wrap->add(createUsernameEdit()); - if (_controls.privacy->value() == Privacy::Private) { + if (_controls.privacy->value() == Privacy::NoUsername) { checkUsernameAvailability(); } } @@ -197,21 +199,19 @@ void Controller::createContent() { void Controller::addRoundButton( not_null container, Privacy value, - const QString &groupText, - const QString &channelText, - rpl::producer groupAbout, - rpl::producer channelAbout) { + const QString &text, + rpl::producer about) { container->add(object_ptr>( container, _controls.privacy, value, - (_isGroup ? groupText : channelText), + text, st::editPeerPrivacyBoxCheckbox)); container->add(object_ptr>( container, object_ptr( container, - std::move(_isGroup ? groupAbout : channelAbout), + std::move(about), st::editPeerPrivacyLabel), st::editPeerPrivacyLabelMargins)); container->add(object_ptr( @@ -242,24 +242,35 @@ void Controller::fillPrivaciesButtons( const auto container = result->entity(); const auto isPublic = _peer->isChannel() - && _peer->asChannel()->isPublic(); + && _peer->asChannel()->hasUsername(); _controls.privacy = std::make_shared>( - savedValue.value_or(isPublic ? Privacy::Public : Privacy::Private)); + savedValue.value_or( + isPublic ? Privacy::HasUsername : Privacy::NoUsername)); addRoundButton( container, - Privacy::Public, - tr::lng_create_public_group_title(tr::now), - tr::lng_create_public_channel_title(tr::now), - tr::lng_create_public_group_about(), - tr::lng_create_public_channel_about()); + Privacy::HasUsername, + (_useLocationPhrases + ? tr::lng_create_permanent_link_title + : _isGroup + ? tr::lng_create_public_group_title + : tr::lng_create_public_channel_title)(tr::now), + (_isGroup + ? tr::lng_create_public_group_about + : tr::lng_create_public_channel_about)()); addRoundButton( container, - Privacy::Private, - tr::lng_create_private_group_title(tr::now), - tr::lng_create_private_channel_title(tr::now), - tr::lng_create_private_group_about(), - tr::lng_create_private_channel_about()); + Privacy::NoUsername, + (_useLocationPhrases + ? tr::lng_create_invite_link_title + : _isGroup + ? tr::lng_create_private_group_title + : tr::lng_create_private_channel_title)(tr::now), + (_useLocationPhrases + ? tr::lng_create_invite_link_about + : _isGroup + ? tr::lng_create_private_group_about + : tr::lng_create_private_channel_about)()); _controls.privacy->setChangedCallback([=](Privacy value) { privacyChanged(value); @@ -343,7 +354,7 @@ object_ptr Controller::createUsernameEdit() { &Ui::UsernameInput::changed, [this] { usernameChanged(); }); - const auto shown = (_controls.privacy->value() == Privacy::Public); + const auto shown = (_controls.privacy->value() == Privacy::HasUsername); result->toggle(shown, anim::type::instant); return std::move(result); @@ -352,14 +363,14 @@ object_ptr Controller::createUsernameEdit() { void Controller::privacyChanged(Privacy value) { const auto toggleEditUsername = [&] { _controls.usernameWrap->toggle( - (value == Privacy::Public), + (value == Privacy::HasUsername), anim::type::instant); }; const auto refreshVisibilities = [&] { // Now first we need to hide that was shown. // Otherwise box will change own Y position. - if (value == Privacy::Public) { + if (value == Privacy::HasUsername) { refreshCreateInviteLink(); refreshEditInviteLink(); toggleEditUsername(); @@ -372,12 +383,12 @@ void Controller::privacyChanged(Privacy value) { refreshEditInviteLink(); } }; - if (value == Privacy::Public) { + if (value == Privacy::HasUsername) { if (_usernameState == UsernameState::TooMany) { askUsernameRevoke(); return; } else if (_usernameState == UsernameState::NotAvailable) { - _controls.privacy->setValue(Privacy::Private); + _controls.privacy->setValue(Privacy::NoUsername); return; } refreshVisibilities(); @@ -394,7 +405,7 @@ void Controller::checkUsernameAvailability() { if (!_controls.usernameInput) { return; } - const auto initial = (_controls.privacy->value() != Privacy::Public); + const auto initial = (_controls.privacy->value() != Privacy::HasUsername); const auto checking = initial ? qsl(".bad.") : getUsernameInput(); @@ -425,14 +436,14 @@ void Controller::checkUsernameAvailability() { _usernameState = UsernameState::Normal; if (type == qstr("CHANNEL_PUBLIC_GROUP_NA")) { _usernameState = UsernameState::NotAvailable; - _controls.privacy->setValue(Privacy::Private); + _controls.privacy->setValue(Privacy::NoUsername); } else if (type == qstr("CHANNELS_ADMIN_PUBLIC_TOO_MUCH")) { _usernameState = UsernameState::TooMany; - if (_controls.privacy->value() == Privacy::Public) { + if (_controls.privacy->value() == Privacy::HasUsername) { askUsernameRevoke(); } } else if (initial) { - if (_controls.privacy->value() == Privacy::Public) { + if (_controls.privacy->value() == Privacy::HasUsername) { _controls.usernameResult = nullptr; setFocusUsername(); } @@ -446,10 +457,10 @@ void Controller::checkUsernameAvailability() { } void Controller::askUsernameRevoke() { - _controls.privacy->setValue(Privacy::Private); + _controls.privacy->setValue(Privacy::NoUsername); const auto revokeCallback = crl::guard(this, [this] { _usernameState = UsernameState::Normal; - _controls.privacy->setValue(Privacy::Public); + _controls.privacy->setValue(Privacy::HasUsername); checkUsernameAvailability(); }); Ui::show( @@ -683,20 +694,26 @@ void Controller::refreshCreateInviteLink() { bool Controller::inviteLinkShown() { return !_controls.privacy - || (_controls.privacy->value() == Privacy::Private) + || (_controls.privacy->value() == Privacy::NoUsername) || _isInviteLink; } } // namespace +EditPeerTypeBox::EditPeerTypeBox(QWidget*, not_null peer) +: EditPeerTypeBox(nullptr, peer, false, {}, {}, {}, {}) { +} + EditPeerTypeBox::EditPeerTypeBox( QWidget*, not_null peer, + bool useLocationPhrases, std::optional> savedCallback, std::optional privacySaved, std::optional usernameSaved, std::optional> usernameError) : _peer(peer) +, _useLocationPhrases(useLocationPhrases) , _savedCallback(std::move(savedCallback)) , _privacySavedValue(privacySaved) , _usernameSavedValue(usernameSaved) @@ -716,6 +733,7 @@ void EditPeerTypeBox::prepare() { this, content, _peer, + _useLocationPhrases, _privacySavedValue, _usernameSavedValue); _focusRequests.events( @@ -735,14 +753,14 @@ void EditPeerTypeBox::prepare() { if (!controller->isInviteLink() && _savedCallback.has_value()) { addButton(tr::lng_settings_save(), [=] { const auto v = controller->getPrivacy(); - if (!controller->isAllowSave() && (v == Privacy::Public)) { + if (!controller->isAllowSave() && (v == Privacy::HasUsername)) { controller->setFocusUsername(); return; } auto local = std::move(*_savedCallback); local(v, - (v == Privacy::Public) + (v == Privacy::HasUsername) ? controller->getUsernameInput() : QString()); // We dont need username with private type. closeBox(); diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_type_box.h b/Telegram/SourceFiles/boxes/peers/edit_peer_type_box.h index 767d8e787..2d4dcf1cf 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_type_box.h +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_type_box.h @@ -25,8 +25,8 @@ class Button; } // namespace Info enum class Privacy { - Public, - Private, + HasUsername, + NoUsername, }; enum class UsernameState { @@ -37,12 +37,16 @@ enum class UsernameState { class EditPeerTypeBox : public BoxContent { public: + // Edit just the invite link. + EditPeerTypeBox(QWidget*, not_null peer); + EditPeerTypeBox( QWidget*, - not_null p, - std::optional> savedCallback = {}, - std::optional privacySaved = {}, - std::optional usernameSaved = {}, + not_null peer, + bool useLocationPhrases, + std::optional> savedCallback, + std::optional privacySaved, + std::optional usernameSaved, std::optional> usernameError = {}); protected: @@ -51,6 +55,7 @@ protected: private: not_null _peer; + bool _useLocationPhrases = false; std::optional> _savedCallback; std::optional _privacySavedValue; diff --git a/Telegram/SourceFiles/data/data_channel.cpp b/Telegram/SourceFiles/data/data_channel.cpp index ca1ba4f83..d8e56e11f 100644 --- a/Telegram/SourceFiles/data/data_channel.cpp +++ b/Telegram/SourceFiles/data/data_channel.cpp @@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_chat.h" #include "data/data_session.h" #include "data/data_folder.h" +#include "data/data_location.h" #include "history/history.h" #include "observer_peer.h" #include "auth_session.h" @@ -32,6 +33,14 @@ void MegagroupInfo::setMigrateFromChat(ChatData *chat) { _migratedFrom = chat; } +const ChannelLocation *MegagroupInfo::getLocation() const { + return _location.address.isEmpty() ? nullptr : &_location; +} + +void MegagroupInfo::setLocation(const ChannelLocation &location) { + _location = location; +} + ChannelData::ChannelData(not_null owner, PeerId id) : PeerData(owner, id) , inputChannel(MTP_inputChannel(MTP_int(bareId()), MTP_long(0))) { @@ -92,6 +101,37 @@ bool ChannelData::canHaveInviteLink() const { || amCreator(); } +void ChannelData::setLocation(const MTPChannelLocation &data) { + if (!mgInfo) { + return; + } + const auto was = mgInfo->getLocation(); + const auto wasValue = was ? *was : ChannelLocation(); + data.match([&](const MTPDchannelLocation &data) { + data.vgeo_point.match([&](const MTPDgeoPoint &point) { + mgInfo->setLocation({ + qs(data.vaddress), + Data::LocationPoint(point) + }); + }, [&](const MTPDgeoPointEmpty &) { + mgInfo->setLocation(ChannelLocation()); + }); + }, [&](const MTPDchannelLocationEmpty &) { + mgInfo->setLocation(ChannelLocation()); + }); + const auto now = mgInfo->getLocation(); + const auto nowValue = now ? *now : ChannelLocation(); + if (was != now || (was && wasValue != nowValue)) { + Notify::peerUpdatedDelayed( + this, + Notify::PeerUpdate::Flag::ChannelLocation); + } +} + +const ChannelLocation *ChannelData::getLocation() const { + return mgInfo ? mgInfo->getLocation() : nullptr; +} + void ChannelData::setLinkedChat(ChannelData *linked) { if (_linkedChat != linked) { _linkedChat = linked; @@ -600,11 +640,14 @@ void ApplyChannelUpdate( ? update.vkicked_count.v : 0); channel->setInviteLink(update.vexported_invite.match([&]( - const MTPDchatInviteExported & data) { + const MTPDchatInviteExported &data) { return qs(data.vlink); }, [&](const MTPDchatInviteEmpty &) { return QString(); })); + channel->setLocation(update.has_location() + ? update.vlocation + : MTPChannelLocation(MTP_channelLocationEmpty())); channel->setLinkedChat(update.has_linked_chat_id() ? channel->owner().channelLoaded(update.vlinked_chat_id.v) : nullptr); diff --git a/Telegram/SourceFiles/data/data_channel.h b/Telegram/SourceFiles/data/data_channel.h index 9d6d9d9ea..127d27cd8 100644 --- a/Telegram/SourceFiles/data/data_channel.h +++ b/Telegram/SourceFiles/data/data_channel.h @@ -9,6 +9,25 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_peer.h" #include "data/data_pts_waiter.h" +#include "data/data_location.h" + +struct ChannelLocation { + QString address; + Data::LocationPoint point; + + friend inline bool operator==( + const ChannelLocation &a, + const ChannelLocation &b) { + return a.address.isEmpty() + ? b.address.isEmpty() + : (a.address == b.address && a.point == b.point); + } + friend inline bool operator!=( + const ChannelLocation &a, + const ChannelLocation &b) { + return !(a == b); + } +}; class MegagroupInfo { public: @@ -34,6 +53,9 @@ public: ChatData *getMigrateFromChat() const; void setMigrateFromChat(ChatData *chat); + const ChannelLocation *getLocation() const; + void setLocation(const ChannelLocation &location); + std::deque> lastParticipants; base::flat_map, Admin> lastAdmins; base::flat_map, Restricted> lastRestricted; @@ -57,6 +79,7 @@ public: private: ChatData *_migratedFrom = nullptr; + ChannelLocation _location; }; @@ -79,7 +102,8 @@ public: static constexpr auto kEssentialFullFlags = 0 | MTPDchannelFull::Flag::f_can_view_participants | MTPDchannelFull::Flag::f_can_set_username - | MTPDchannelFull::Flag::f_can_set_stickers; + | MTPDchannelFull::Flag::f_can_set_stickers + | MTPDchannelFull::Flag::f_location; using FullFlags = Data::Flags< MTPDchannelFull::Flags, kEssentialFullFlags>; @@ -206,9 +230,15 @@ public: bool isBroadcast() const { return flags() & MTPDchannel::Flag::f_broadcast; } - bool isPublic() const { + bool hasUsername() const { return flags() & MTPDchannel::Flag::f_username; } + bool hasLocation() const { + return fullFlags() & MTPDchannelFull::Flag::f_location; + } + bool isPublic() const { + return hasUsername() || hasLocation(); + } bool amCreator() const { return flags() & MTPDchannel::Flag::f_creator; } @@ -279,6 +309,9 @@ public: QString inviteLink() const; bool canHaveInviteLink() const; + void setLocation(const MTPChannelLocation &data); + const ChannelLocation *getLocation() const; + void setLinkedChat(ChannelData *linked); ChannelData *linkedChat() const; diff --git a/Telegram/SourceFiles/data/data_location.cpp b/Telegram/SourceFiles/data/data_location.cpp new file mode 100644 index 000000000..0c608b868 --- /dev/null +++ b/Telegram/SourceFiles/data/data_location.cpp @@ -0,0 +1,44 @@ +/* +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 "data/data_location.h" + +#include "ui/image/image.h" +#include "data/data_file_origin.h" + +namespace Data { +namespace { + +GeoPointLocation ComputeLocation(const Data::LocationPoint &point) { + const auto scale = 1 + (cScale() * cIntRetinaFactor()) / 200; + const auto zoom = 13 + (scale - 1); + const auto w = st::locationSize.width() / scale; + const auto h = st::locationSize.height() / scale; + + auto result = GeoPointLocation(); + result.lat = point.lat(); + result.lon = point.lon(); + result.access = point.accessHash(); + result.width = w; + result.height = h; + result.zoom = zoom; + result.scale = scale; + return result; +} + +} // namespace + +LocationThumbnail::LocationThumbnail(const LocationPoint &point) +: point(point) +, thumb(Images::Create(ComputeLocation(point))) { +} + +void LocationThumbnail::load(FileOrigin origin) { + thumb->load(origin); +} + +} // namespace Data diff --git a/Telegram/SourceFiles/data/data_location.h b/Telegram/SourceFiles/data/data_location.h new file mode 100644 index 000000000..d98fcbc57 --- /dev/null +++ b/Telegram/SourceFiles/data/data_location.h @@ -0,0 +1,99 @@ +/* +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 + +namespace Data { + +struct FileOrigin; + +class LocationPoint { +public: + LocationPoint() = default; + explicit LocationPoint(const MTPDgeoPoint &point) + : _lat(point.vlat.v) + , _lon(point.vlong.v) + , _access(point.vaccess_hash.v) { + } + + QString latAsString() const { + return AsString(_lat); + } + QString lonAsString() const { + return AsString(_lon); + } + MTPGeoPoint toMTP() const { + return MTP_geoPoint( + MTP_double(_lon), + MTP_double(_lat), + MTP_long(_access)); + } + + float64 lat() const { + return _lat; + } + float64 lon() const { + return _lon; + } + uint64 accessHash() const { + return _access; + } + + inline size_t hash() const { +#ifndef OS_MAC_OLD + return QtPrivate::QHashCombine().operator()( + std::hash()(_lat), + _lon); +#else // OS_MAC_OLD + const auto h1 = std::hash()(_lat); + const auto h2 = std::hash()(_lon); + return ((h1 << 16) | (h1 >> 16)) ^ h2; +#endif // OS_MAC_OLD + } + +private: + static QString AsString(float64 value) { + constexpr auto kPrecision = 6; + return QString::number(value, 'f', kPrecision); + } + + friend inline bool operator==(const LocationPoint &a, const LocationPoint &b) { + return (a._lat == b._lat) && (a._lon == b._lon); + } + + friend inline bool operator<(const LocationPoint &a, const LocationPoint &b) { + return (a._lat < b._lat) || ((a._lat == b._lat) && (a._lon < b._lon)); + } + + float64 _lat = 0; + float64 _lon = 0; + uint64 _access = 0; + +}; + +struct LocationThumbnail { + LocationThumbnail(const LocationPoint &point); + + LocationPoint point; + ImagePtr thumb; + + void load(FileOrigin origin); + +}; + +} // namespace Data + +namespace std { + +template <> +struct hash { + size_t operator()(const Data::LocationPoint &value) const { + return value.hash(); + } +}; + +} // namespace std diff --git a/Telegram/SourceFiles/data/data_media_types.cpp b/Telegram/SourceFiles/data/data_media_types.cpp index bc271008d..7a30f0e57 100644 --- a/Telegram/SourceFiles/data/data_media_types.cpp +++ b/Telegram/SourceFiles/data/data_media_types.cpp @@ -168,7 +168,7 @@ const Invoice *Media::invoice() const { return nullptr; } -LocationData *Media::location() const { +LocationThumbnail *Media::location() const { return nullptr; } @@ -861,17 +861,17 @@ std::unique_ptr MediaContact::createView( MediaLocation::MediaLocation( not_null parent, - const LocationCoords &coords) -: MediaLocation(parent, coords, QString(), QString()) { + const LocationPoint &point) +: MediaLocation(parent, point, QString(), QString()) { } MediaLocation::MediaLocation( not_null parent, - const LocationCoords &coords, + const LocationPoint &point, const QString &title, const QString &description) : Media(parent) -, _location(parent->history()->owner().location(coords)) +, _location(parent->history()->owner().location(point)) , _title(title) , _description(description) { } @@ -879,12 +879,12 @@ MediaLocation::MediaLocation( std::unique_ptr MediaLocation::clone(not_null parent) { return std::make_unique( parent, - _location->coords, + _location->point, _title, _description); } -LocationData *MediaLocation::location() const { +LocationThumbnail *MediaLocation::location() const { return _location; } @@ -915,7 +915,7 @@ TextForMimeData MediaLocation::clipboardText() const { if (!descriptionResult.text.isEmpty()) { result.append(std::move(descriptionResult)); } - result.append(LocationClickHandler(_location->coords).dragText()); + result.append(LocationClickHandler(_location->point).dragText()); return result; } diff --git a/Telegram/SourceFiles/data/data_media_types.h b/Telegram/SourceFiles/data/data_media_types.h index 21341fd6a..04a314623 100644 --- a/Telegram/SourceFiles/data/data_media_types.h +++ b/Telegram/SourceFiles/data/data_media_types.h @@ -9,8 +9,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL class HistoryItem; class HistoryMedia; -class LocationCoords; -struct LocationData; namespace base { template @@ -29,6 +27,9 @@ class Element; namespace Data { +class LocationPoint; +struct LocationThumbnail; + enum class CallFinishReason : char { Missed, Busy, @@ -76,7 +77,7 @@ public: virtual const Call *call() const; virtual GameData *game() const; virtual const Invoice *invoice() const; - virtual LocationData *location() const; + virtual LocationThumbnail *location() const; virtual PollData *poll() const; virtual bool uploading() const; @@ -226,16 +227,16 @@ class MediaLocation : public Media { public: MediaLocation( not_null parent, - const LocationCoords &coords); + const LocationPoint &point); MediaLocation( not_null parent, - const LocationCoords &coords, + const LocationPoint &point, const QString &title, const QString &description); std::unique_ptr clone(not_null parent) override; - LocationData *location() const override; + LocationThumbnail *location() const override; QString chatListText() const override; QString notificationText() const override; QString pinnedTextSubstring() const override; @@ -248,7 +249,7 @@ public: not_null realParent) override; private: - not_null _location; + not_null _location; QString _title; QString _description; diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 22635b207..46da45468 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -2885,14 +2885,13 @@ void Session::applyUpdate(const MTPDupdateChatDefaultBannedRights &update) { } } -not_null Session::location(const LocationCoords &coords) { - auto i = _locations.find(coords); - if (i == _locations.cend()) { - i = _locations.emplace( - coords, - std::make_unique(coords)).first; - } - return i->second.get(); +not_null Session::location(const LocationPoint &point) { + const auto i = _locations.find(point); + return (i != _locations.cend()) + ? i->second.get() + : _locations.emplace( + point, + std::make_unique(point)).first->second.get(); } void Session::registerPhotoItem( diff --git a/Telegram/SourceFiles/data/data_session.h b/Telegram/SourceFiles/data/data_session.h index b84e66ea0..6834bf262 100644 --- a/Telegram/SourceFiles/data/data_session.h +++ b/Telegram/SourceFiles/data/data_session.h @@ -58,7 +58,7 @@ struct SavedCredentials; namespace Data { class Folder; - +class LocationPoint; class WallPaper; class Session final { @@ -521,8 +521,8 @@ public: not_null processPoll(const MTPPoll &data); not_null processPoll(const MTPDmessageMediaPoll &data); - [[nodiscard]] not_null location( - const LocationCoords &coords); + [[nodiscard]] not_null location( + const LocationPoint &point); void registerPhotoItem( not_null photo, @@ -895,8 +895,8 @@ private: not_null, base::flat_set>> _webpageViews; std::unordered_map< - LocationCoords, - std::unique_ptr> _locations; + LocationPoint, + std::unique_ptr> _locations; std::unordered_map< PollId, std::unique_ptr> _polls; diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_item.cpp b/Telegram/SourceFiles/history/admin_log/history_admin_log_item.cpp index 0cc775cb3..70137da4b 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_item.cpp +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_item.cpp @@ -667,7 +667,7 @@ void GenerateItems( const auto address = qs(data.vaddress); const auto link = data.vgeo_point.match([&](const MTPDgeoPoint &data) { return textcmdLink( - LocationClickHandler::Url(LocationCoords(data)), + LocationClickHandler::Url(Data::LocationPoint(data)), address); }, [&](const MTPDgeoPointEmpty &) { return address; diff --git a/Telegram/SourceFiles/history/history_location_manager.cpp b/Telegram/SourceFiles/history/history_location_manager.cpp index 9b04fc3a0..a46f8d8d6 100644 --- a/Telegram/SourceFiles/history/history_location_manager.cpp +++ b/Telegram/SourceFiles/history/history_location_manager.cpp @@ -18,23 +18,6 @@ namespace { constexpr auto kCoordPrecision = 8; constexpr auto kMaxHttpRedirects = 5; -GeoPointLocation ComputeLocation(const LocationCoords &coords) { - const auto scale = 1 + (cScale() * cIntRetinaFactor()) / 200; - const auto zoom = 13 + (scale - 1); - const auto w = st::locationSize.width() / scale; - const auto h = st::locationSize.height() / scale; - - auto result = GeoPointLocation(); - result.lat = coords.lat(); - result.lon = coords.lon(); - result.access = coords.accessHash(); - result.width = w; - result.height = h; - result.zoom = zoom; - result.scale = scale; - return result; -} - } // namespace QString LocationClickHandler::copyToClipboardText() const { @@ -46,25 +29,16 @@ QString LocationClickHandler::copyToClipboardContextItemText() const { } void LocationClickHandler::onClick(ClickContext context) const { - if (!psLaunchMaps(_coords)) { + if (!psLaunchMaps(_point)) { QDesktopServices::openUrl(_text); } } void LocationClickHandler::setup() { - _text = Url(_coords); + _text = Url(_point); } -QString LocationClickHandler::Url(const LocationCoords &coords) { - const auto latlon = coords.latAsString() + ',' + coords.lonAsString(); +QString LocationClickHandler::Url(const Data::LocationPoint &point) { + const auto latlon = point.latAsString() + ',' + point.lonAsString(); return qsl("https://maps.google.com/maps?q=") + latlon + qsl("&ll=") + latlon + qsl("&z=16"); } - -LocationData::LocationData(const LocationCoords &coords) -: coords(coords) -, thumb(Images::Create(ComputeLocation(coords))) { -} - -void LocationData::load(Data::FileOrigin origin) { - thumb->load(origin); -} diff --git a/Telegram/SourceFiles/history/history_location_manager.h b/Telegram/SourceFiles/history/history_location_manager.h index 30eb82741..97f7e9c2a 100644 --- a/Telegram/SourceFiles/history/history_location_manager.h +++ b/Telegram/SourceFiles/history/history_location_manager.h @@ -7,98 +7,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -class LocationCoords { -public: - LocationCoords() = default; - explicit LocationCoords(const MTPDgeoPoint &point) - : _lat(point.vlat.v) - , _lon(point.vlong.v) - , _access(point.vaccess_hash.v) { - } - - QString latAsString() const { - return asString(_lat); - } - QString lonAsString() const { - return asString(_lon); - } - MTPGeoPoint toMTP() const { - return MTP_geoPoint( - MTP_double(_lon), - MTP_double(_lat), - MTP_long(_access)); - } - - float64 lat() const { - return _lat; - } - float64 lon() const { - return _lon; - } - uint64 accessHash() const { - return _access; - } - - inline size_t hash() const { -#ifndef OS_MAC_OLD - return QtPrivate::QHashCombine().operator()( - std::hash()(_lat), - _lon); -#else // OS_MAC_OLD - const auto h1 = std::hash()(_lat); - const auto h2 = std::hash()(_lon); - return ((h1 << 16) | (h1 >> 16)) ^ h2; -#endif // OS_MAC_OLD - } - -private: - static QString asString(float64 value) { - constexpr auto kPrecision = 6; - return QString::number(value, 'f', kPrecision); - } - - friend inline bool operator==(const LocationCoords &a, const LocationCoords &b) { - return (a._lat == b._lat) && (a._lon == b._lon); - } - - friend inline bool operator<(const LocationCoords &a, const LocationCoords &b) { - return (a._lat < b._lat) || ((a._lat == b._lat) && (a._lon < b._lon)); - } - - float64 _lat = 0; - float64 _lon = 0; - uint64 _access = 0; - -}; - -namespace std { - -template <> -struct hash { - size_t operator()(const LocationCoords &value) const { - return value.hash(); - } -}; - -} // namespace std - -struct LocationData { - LocationData(const LocationCoords &coords); - - LocationCoords coords; - ImagePtr thumb; - - void load(Data::FileOrigin origin); - -}; +#include "data/data_location.h" class LocationClickHandler : public ClickHandler { public: - LocationClickHandler(const LocationCoords &coords) : _coords(coords) { + LocationClickHandler(const Data::LocationPoint &point) + : _point(point) { setup(); } - static QString Url(const LocationCoords &coords); + static QString Url(const Data::LocationPoint &coords); void onClick(ClickContext context) const override; @@ -116,7 +34,7 @@ public: private: void setup(); - LocationCoords _coords; + Data::LocationPoint _point; QString _text; }; diff --git a/Telegram/SourceFiles/history/history_message.cpp b/Telegram/SourceFiles/history/history_message.cpp index d2ae90cef..9a01287a9 100644 --- a/Telegram/SourceFiles/history/history_message.cpp +++ b/Telegram/SourceFiles/history/history_message.cpp @@ -789,7 +789,7 @@ std::unique_ptr HistoryMessage::CreateMedia( return media.vgeo.match([&](const MTPDgeoPoint &point) -> Result { return std::make_unique( item, - LocationCoords(point)); + Data::LocationPoint(point)); }, [](const MTPDgeoPointEmpty &) -> Result { return nullptr; }); @@ -797,7 +797,7 @@ std::unique_ptr HistoryMessage::CreateMedia( return media.vgeo.match([&](const MTPDgeoPoint &point) -> Result { return std::make_unique( item, - LocationCoords(point)); + Data::LocationPoint(point)); }, [](const MTPDgeoPointEmpty &) -> Result { return nullptr; }); @@ -805,7 +805,7 @@ std::unique_ptr HistoryMessage::CreateMedia( return media.vgeo.match([&](const MTPDgeoPoint &point) -> Result { return std::make_unique( item, - LocationCoords(point), + Data::LocationPoint(point), qs(media.vtitle), qs(media.vaddress)); }, [](const MTPDgeoPointEmpty &data) -> Result { diff --git a/Telegram/SourceFiles/history/media/history_media_location.cpp b/Telegram/SourceFiles/history/media/history_media_location.cpp index 0b20111bf..94cd73d80 100644 --- a/Telegram/SourceFiles/history/media/history_media_location.cpp +++ b/Telegram/SourceFiles/history/media/history_media_location.cpp @@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/image/image.h" #include "ui/text_options.h" #include "data/data_file_origin.h" +#include "data/data_location.h" #include "styles/style_history.h" namespace { @@ -26,14 +27,14 @@ using TextState = HistoryView::TextState; HistoryLocation::HistoryLocation( not_null parent, - not_null location, + not_null location, const QString &title, const QString &description) : HistoryMedia(parent) , _data(location) , _title(st::msgMinWidth) , _description(st::msgMinWidth) -, _link(std::make_shared(_data->coords)) { +, _link(std::make_shared(_data->point)) { if (!title.isEmpty()) { _title.setText( st::webPageTitleStyle, diff --git a/Telegram/SourceFiles/history/media/history_media_location.h b/Telegram/SourceFiles/history/media/history_media_location.h index d815e99dc..b511e83a5 100644 --- a/Telegram/SourceFiles/history/media/history_media_location.h +++ b/Telegram/SourceFiles/history/media/history_media_location.h @@ -9,14 +9,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/media/history_media.h" -class LocationCoords; -struct LocationData; +namespace Data { +struct LocationThumbnail; +} // namespace Data class HistoryLocation : public HistoryMedia { public: HistoryLocation( not_null parent, - not_null location, + not_null location, const QString &title = QString(), const QString &description = QString()); @@ -58,7 +59,7 @@ private: TextSelection toDescriptionSelection(TextSelection selection) const; TextSelection fromDescriptionSelection(TextSelection selection) const; - LocationData *_data; + const not_null _data; Ui::Text::String _title, _description; ClickHandlerPtr _link; diff --git a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp index 6549381d9..0327149fb 100644 --- a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp +++ b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp @@ -521,7 +521,7 @@ void CopyPostLink(FullMsgId itemId) { const auto channel = item->history()->peer->asChannel(); Assert(channel != nullptr); - Ui::Toast::Show(channel->isPublic() + Ui::Toast::Show(channel->hasUsername() ? tr::lng_channel_public_link_copied(tr::now) : tr::lng_context_about_private_link(tr::now)); } diff --git a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp index b58c9d137..8379cb17e 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp @@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/labels.h" #include "ui/toast/toast.h" #include "ui/text/text_utilities.h" // Ui::Text::ToUpper +#include "history/history_location_manager.h" // LocationClickHandler. #include "boxes/abstract_box.h" #include "boxes/confirm_box.h" #include "boxes/peer_list_box.h" @@ -249,11 +250,11 @@ object_ptr DetailsFiller::setupInfo() { result->setContextCopyText(contextCopyText); return result; }; - if (auto user = _peer->asUser()) { - if (Auth().supportMode()) { + if (const auto user = _peer->asUser()) { + if (user->session().supportMode()) { addInfoLineGeneric( - Auth().supportHelper().infoLabelValue(user), - Auth().supportHelper().infoTextValue(user)); + user->session().supportHelper().infoLabelValue(user), + user->session().supportHelper().infoTextValue(user)); } addInfoOneLine( @@ -273,26 +274,20 @@ object_ptr DetailsFiller::setupInfo() { auto linkText = LinkValue( _peer ) | rpl::map([](const QString &link) { - auto result = TextWithEntities{ link, {} }; - if (!link.isEmpty()) { - auto remove = qstr("https://"); - if (result.text.startsWith(remove)) { - result.text.remove(0, remove.size()); - } - result.entities.push_back({ - EntityType::CustomUrl, - 0, - result.text.size(), - link }); - } - return result; + return link.isEmpty() + ? TextWithEntities() + : Ui::Text::Link( + (link.startsWith(qstr("https://")) + ? link.mid(qstr("https://").size()) + : link), + link); }); auto link = addInfoOneLine( tr::lng_info_link_label(), std::move(linkText), QString()); link->setClickHandlerFilter([peer = _peer](auto&&...) { - auto link = Core::App().createInternalLinkFull( + const auto link = Core::App().createInternalLinkFull( peer->userName()); if (!link.isEmpty()) { QApplication::clipboard()->setText(link); @@ -300,6 +295,24 @@ object_ptr DetailsFiller::setupInfo() { } return false; }); + + if (const auto channel = _peer->asChannel()) { + auto locationText = LocationValue( + channel + ) | rpl::map([](const ChannelLocation *location) { + return location + ? Ui::Text::Link( + location->address, + LocationClickHandler::Url(location->point)) + : TextWithEntities(); + }); + addInfoOneLine( + tr::lng_info_location_label(), + std::move(locationText), + QString() + )->setLinksTrusted(); + } + addInfoLine(tr::lng_info_about_label(), AboutValue(_peer)); } if (!_peer->isSelf()) { diff --git a/Telegram/SourceFiles/info/profile/info_profile_values.cpp b/Telegram/SourceFiles/info/profile/info_profile_values.cpp index e4b9f5c04..6d182cdd5 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_values.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_values.cpp @@ -58,8 +58,8 @@ rpl::producer BioValue(not_null user) { auto PlainUsernameValue(not_null peer) { return Notify::PeerUpdateValue( - peer, - Notify::PeerUpdate::Flag::UsernameChanged + peer, + Notify::PeerUpdate::Flag::UsernameChanged ) | rpl::map([peer] { return peer->userName(); }); @@ -113,6 +113,16 @@ rpl::producer LinkValue(not_null peer) { }); } +rpl::producer LocationValue( + not_null channel) { + return Notify::PeerUpdateValue( + channel, + Notify::PeerUpdate::Flag::ChannelLocation + ) | rpl::map([=] { + return channel->getLocation(); + }); +} + rpl::producer NotificationsEnabledValue(not_null peer) { return rpl::merge( Notify::PeerUpdateValue( diff --git a/Telegram/SourceFiles/info/profile/info_profile_values.h b/Telegram/SourceFiles/info/profile/info_profile_values.h index 346d1a9f0..cb1b62c52 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_values.h +++ b/Telegram/SourceFiles/info/profile/info_profile_values.h @@ -11,6 +11,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include "observer_peer.h" +struct ChannelLocation; + namespace Ui { class RpWidget; template @@ -36,6 +38,8 @@ rpl::producer BioValue(not_null user); rpl::producer UsernameValue(not_null user); rpl::producer AboutValue(not_null peer); rpl::producer LinkValue(not_null peer); +rpl::producer LocationValue( + not_null channel); rpl::producer NotificationsEnabledValue(not_null peer); rpl::producer IsContactValue(not_null user); rpl::producer CanInviteBotToGroupValue(not_null user); diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp index d59171352..64d69fb8a 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp @@ -1025,9 +1025,10 @@ Article::Article(not_null context, Result *result, bool withThumb) : I , _withThumb(withThumb) , _title(st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft - st::inlineThumbSize - st::inlineThumbSkip) , _description(st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft - st::inlineThumbSize - st::inlineThumbSkip) { - LocationCoords location; - if (!_link && result->getLocationCoords(&location)) { - _link = std::make_shared(location); + if (!_link) { + if (const auto point = result->getLocationPoint()) { + _link = std::make_shared(*point); + } } _thumbLetter = getResultThumbLetter(); } diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp b/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp index 02830d061..7efe1019c 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp @@ -223,17 +223,16 @@ std::unique_ptr Result::create(uint64 queryId, const MTPBotInlineResult return nullptr; } - LocationCoords coords; - if (result->getLocationCoords(&coords)) { + if (const auto point = result->getLocationPoint()) { const auto scale = 1 + (cScale() * cIntRetinaFactor()) / 200; const auto zoom = 15 + (scale - 1); const auto w = st::inlineThumbSize / scale; const auto h = st::inlineThumbSize / scale; auto location = GeoPointLocation(); - location.lat = coords.lat(); - location.lon = coords.lon(); - location.access = coords.accessHash(); + location.lat = point->lat(); + location.lon = point->lon(); + location.access = point->accessHash(); location.width = w; location.height = h; location.zoom = zoom; @@ -329,8 +328,8 @@ QString Result::getErrorOnSend(History *history) const { return sendData->getErrorOnSend(this, history); } -bool Result::getLocationCoords(LocationCoords *outLocation) const { - return sendData->getLocationCoords(outLocation); +std::optional Result::getLocationPoint() const { + return sendData->getLocationPoint(); } QString Result::getLayoutTitle() const { diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_result.h b/Telegram/SourceFiles/inline_bots/inline_bot_result.h index f047eb39a..4e490e5d6 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_result.h +++ b/Telegram/SourceFiles/inline_bots/inline_bot_result.h @@ -8,7 +8,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once class FileLoader; -class LocationCoords; + +namespace Data { +class LocationPoint; +} // namespace Data namespace InlineBots { @@ -55,7 +58,7 @@ public: QString getErrorOnSend(History *history) const; // interface for Layout:: usage - bool getLocationCoords(LocationCoords *outLocation) const; + std::optional getLocationPoint() const; QString getLayoutTitle() const; QString getLayoutDescription() const; diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_send_data.h b/Telegram/SourceFiles/inline_bots/inline_bot_send_data.h index 3e3ee1cd6..7416f8d3a 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_send_data.h +++ b/Telegram/SourceFiles/inline_bots/inline_bot_send_data.h @@ -45,8 +45,8 @@ public: virtual bool hasLocationCoords() const { return false; } - virtual bool getLocationCoords(LocationCoords *outLocation) const { - return false; + virtual std::optional getLocationPoint() const { + return std::nullopt; } virtual QString getLayoutTitle(const Result *owner) const; virtual QString getLayoutDescription(const Result *owner) const; @@ -121,14 +121,12 @@ public: bool hasLocationCoords() const override { return true; } - bool getLocationCoords(LocationCoords *outLocation) const override { - Assert(outLocation != nullptr); - *outLocation = _location; - return true; + std::optional getLocationPoint() const override { + return _location; } private: - LocationCoords _location; + Data::LocationPoint _location; }; @@ -153,14 +151,12 @@ public: bool hasLocationCoords() const override { return true; } - bool getLocationCoords(LocationCoords *outLocation) const override { - Assert(outLocation != nullptr); - *outLocation = _location; - return true; + std::optional getLocationPoint() const override { + return _location; } private: - LocationCoords _location; + Data::LocationPoint _location; QString _venueId, _provider, _title, _address; }; diff --git a/Telegram/SourceFiles/observer_peer.h b/Telegram/SourceFiles/observer_peer.h index c47509de4..4eaf46c3c 100644 --- a/Telegram/SourceFiles/observer_peer.h +++ b/Telegram/SourceFiles/observer_peer.h @@ -66,6 +66,7 @@ struct PeerUpdate { ChannelStickersChanged = (1 << 18), ChannelPromotedChanged = (1 << 19), ChannelLinkedChat = (1 << 20), + ChannelLocation = (1 << 21), }; using Flags = base::flags; friend inline constexpr auto is_flag_type(Flag) { return true; } diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index 73dc22149..92252de0c 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -478,6 +478,6 @@ bool linuxMoveFile(const char *from, const char *to) { return true; } -bool psLaunchMaps(const LocationCoords &coords) { +bool psLaunchMaps(const Data::LocationPoint &point) { return false; } diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.h b/Telegram/SourceFiles/platform/linux/specific_linux.h index 3bcceb2df..5bb6a1a0d 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.h +++ b/Telegram/SourceFiles/platform/linux/specific_linux.h @@ -10,7 +10,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include -class LocationCoords; +namespace Data { +class LocationPoint; +} // namespace Data namespace Platform { @@ -104,4 +106,4 @@ public: bool linuxMoveFile(const char *from, const char *to); -bool psLaunchMaps(const LocationCoords &coords); +bool psLaunchMaps(const Data::LocationPoint &point); diff --git a/Telegram/SourceFiles/platform/mac/specific_mac.h b/Telegram/SourceFiles/platform/mac/specific_mac.h index f287614ef..ee354e43b 100644 --- a/Telegram/SourceFiles/platform/mac/specific_mac.h +++ b/Telegram/SourceFiles/platform/mac/specific_mac.h @@ -9,7 +9,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "platform/mac/specific_mac_p.h" -class LocationCoords; +namespace Data { +class LocationPoint; +} // namespace Data namespace Platform { @@ -108,4 +110,4 @@ QString strStyleOfInterface(); QString strTitleWrapClass(); QString strTitleClass(); -bool psLaunchMaps(const LocationCoords &coords); +bool psLaunchMaps(const Data::LocationPoint &point); diff --git a/Telegram/SourceFiles/platform/mac/specific_mac.mm b/Telegram/SourceFiles/platform/mac/specific_mac.mm index c07db9ef5..500e2f89e 100644 --- a/Telegram/SourceFiles/platform/mac/specific_mac.mm +++ b/Telegram/SourceFiles/platform/mac/specific_mac.mm @@ -288,8 +288,8 @@ QByteArray psPathBookmark(const QString &path) { return objc_pathBookmark(path); } -bool psLaunchMaps(const LocationCoords &coords) { - return QDesktopServices::openUrl(qsl("https://maps.apple.com/?q=Point&z=16&ll=%1,%2").arg(coords.latAsString()).arg(coords.lonAsString())); +bool psLaunchMaps(const Data::LocationPoint &point) { + return QDesktopServices::openUrl(qsl("https://maps.apple.com/?q=Point&z=16&ll=%1,%2").arg(point.latAsString()).arg(point.lonAsString())); } QString strNotificationAboutThemeChange() { diff --git a/Telegram/SourceFiles/platform/win/specific_win.cpp b/Telegram/SourceFiles/platform/win/specific_win.cpp index 6648e7fd6..9ae350528 100644 --- a/Telegram/SourceFiles/platform/win/specific_win.cpp +++ b/Telegram/SourceFiles/platform/win/specific_win.cpp @@ -583,6 +583,6 @@ void psWriteDump() { #endif // TDESKTOP_DISABLE_CRASH_REPORTS } -bool psLaunchMaps(const LocationCoords &coords) { - return QDesktopServices::openUrl(qsl("bingmaps:?lvl=16&collection=point.%1_%2_Point").arg(coords.latAsString()).arg(coords.lonAsString())); +bool psLaunchMaps(const Data::LocationPoint &point) { + return QDesktopServices::openUrl(qsl("bingmaps:?lvl=16&collection=point.%1_%2_Point").arg(point.latAsString()).arg(point.lonAsString())); } diff --git a/Telegram/SourceFiles/platform/win/specific_win.h b/Telegram/SourceFiles/platform/win/specific_win.h index 6fd843f49..e50c1323d 100644 --- a/Telegram/SourceFiles/platform/win/specific_win.h +++ b/Telegram/SourceFiles/platform/win/specific_win.h @@ -9,7 +9,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "platform/win/wrapper_windows_h.h" -class LocationCoords; +namespace Data { +class LocationPoint; +} // namespace Data namespace Platform { @@ -107,4 +109,4 @@ public: }; -bool psLaunchMaps(const LocationCoords &coords); +bool psLaunchMaps(const Data::LocationPoint &point); diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index c296280b7..0103f0e51 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -506,7 +506,7 @@ void Filler::addChannelActions(not_null channel) { [channel] { Auth().api().joinChannel(channel); }); } if (_source != PeerMenuSource::ChatsList) { - auto needReport = !channel->amCreator() + const auto needReport = !channel->amCreator() && (!isGroup || channel->isPublic()); if (needReport) { _addAction(tr::lng_profile_report(tr::now), [channel] { diff --git a/Telegram/gyp/telegram_sources.txt b/Telegram/gyp/telegram_sources.txt index 0fdb69629..652dc5590 100644 --- a/Telegram/gyp/telegram_sources.txt +++ b/Telegram/gyp/telegram_sources.txt @@ -190,6 +190,8 @@ <(src_loc)/data/data_game.h <(src_loc)/data/data_groups.cpp <(src_loc)/data/data_groups.h +<(src_loc)/data/data_location.cpp +<(src_loc)/data/data_location.h <(src_loc)/data/data_media_types.cpp <(src_loc)/data/data_media_types.h <(src_loc)/data/data_messages.cpp