diff --git a/Telegram/Resources/icons/info_actions.png b/Telegram/Resources/icons/info_actions.png new file mode 100644 index 000000000..30c270a73 Binary files /dev/null and b/Telegram/Resources/icons/info_actions.png differ diff --git a/Telegram/Resources/icons/info_actions@2x.png b/Telegram/Resources/icons/info_actions@2x.png new file mode 100644 index 000000000..65aa8cf4b Binary files /dev/null and b/Telegram/Resources/icons/info_actions@2x.png differ diff --git a/Telegram/Resources/icons/info_add_member.png b/Telegram/Resources/icons/info_add_member.png new file mode 100644 index 000000000..db24d8a74 Binary files /dev/null and b/Telegram/Resources/icons/info_add_member.png differ diff --git a/Telegram/Resources/icons/info_add_member@2x.png b/Telegram/Resources/icons/info_add_member@2x.png new file mode 100644 index 000000000..a81e5bd06 Binary files /dev/null and b/Telegram/Resources/icons/info_add_member@2x.png differ diff --git a/Telegram/Resources/icons/info_back.png b/Telegram/Resources/icons/info_back.png new file mode 100644 index 000000000..e53ce913d Binary files /dev/null and b/Telegram/Resources/icons/info_back.png differ diff --git a/Telegram/Resources/icons/info_back@2x.png b/Telegram/Resources/icons/info_back@2x.png new file mode 100644 index 000000000..aac5c40e9 Binary files /dev/null and b/Telegram/Resources/icons/info_back@2x.png differ diff --git a/Telegram/Resources/icons/info_close.png b/Telegram/Resources/icons/info_close.png new file mode 100644 index 000000000..51520916b Binary files /dev/null and b/Telegram/Resources/icons/info_close.png differ diff --git a/Telegram/Resources/icons/info_close@2x.png b/Telegram/Resources/icons/info_close@2x.png new file mode 100644 index 000000000..94b5089f9 Binary files /dev/null and b/Telegram/Resources/icons/info_close@2x.png differ diff --git a/Telegram/Resources/icons/info_common_groups.png b/Telegram/Resources/icons/info_common_groups.png new file mode 100644 index 000000000..610fc18c1 Binary files /dev/null and b/Telegram/Resources/icons/info_common_groups.png differ diff --git a/Telegram/Resources/icons/info_common_groups@2x.png b/Telegram/Resources/icons/info_common_groups@2x.png new file mode 100644 index 000000000..0950b391f Binary files /dev/null and b/Telegram/Resources/icons/info_common_groups@2x.png differ diff --git a/Telegram/Resources/icons/info_information.png b/Telegram/Resources/icons/info_information.png new file mode 100644 index 000000000..60f49e72b Binary files /dev/null and b/Telegram/Resources/icons/info_information.png differ diff --git a/Telegram/Resources/icons/info_information@2x.png b/Telegram/Resources/icons/info_information@2x.png new file mode 100644 index 000000000..dd0091259 Binary files /dev/null and b/Telegram/Resources/icons/info_information@2x.png differ diff --git a/Telegram/Resources/icons/info_media_audio.png b/Telegram/Resources/icons/info_media_audio.png new file mode 100644 index 000000000..10c6061d8 Binary files /dev/null and b/Telegram/Resources/icons/info_media_audio.png differ diff --git a/Telegram/Resources/icons/info_media_audio@2x.png b/Telegram/Resources/icons/info_media_audio@2x.png new file mode 100644 index 000000000..29879a51f Binary files /dev/null and b/Telegram/Resources/icons/info_media_audio@2x.png differ diff --git a/Telegram/Resources/icons/info_media_link.png b/Telegram/Resources/icons/info_media_link.png new file mode 100644 index 000000000..376cdcef3 Binary files /dev/null and b/Telegram/Resources/icons/info_media_link.png differ diff --git a/Telegram/Resources/icons/info_media_link@2x.png b/Telegram/Resources/icons/info_media_link@2x.png new file mode 100644 index 000000000..0a8acd780 Binary files /dev/null and b/Telegram/Resources/icons/info_media_link@2x.png differ diff --git a/Telegram/Resources/icons/info_media_photo.png b/Telegram/Resources/icons/info_media_photo.png new file mode 100644 index 000000000..7b7fea3d8 Binary files /dev/null and b/Telegram/Resources/icons/info_media_photo.png differ diff --git a/Telegram/Resources/icons/info_media_photo@2x.png b/Telegram/Resources/icons/info_media_photo@2x.png new file mode 100644 index 000000000..3eeb6242e Binary files /dev/null and b/Telegram/Resources/icons/info_media_photo@2x.png differ diff --git a/Telegram/Resources/icons/info_media_round.png b/Telegram/Resources/icons/info_media_round.png new file mode 100644 index 000000000..012cd90c5 Binary files /dev/null and b/Telegram/Resources/icons/info_media_round.png differ diff --git a/Telegram/Resources/icons/info_media_round@2x.png b/Telegram/Resources/icons/info_media_round@2x.png new file mode 100644 index 000000000..825b7ceed Binary files /dev/null and b/Telegram/Resources/icons/info_media_round@2x.png differ diff --git a/Telegram/Resources/icons/info_media_voice.png b/Telegram/Resources/icons/info_media_voice.png new file mode 100644 index 000000000..8a476735a Binary files /dev/null and b/Telegram/Resources/icons/info_media_voice.png differ diff --git a/Telegram/Resources/icons/info_media_voice@2x.png b/Telegram/Resources/icons/info_media_voice@2x.png new file mode 100644 index 000000000..a4daf1d7c Binary files /dev/null and b/Telegram/Resources/icons/info_media_voice@2x.png differ diff --git a/Telegram/Resources/icons/info_members.png b/Telegram/Resources/icons/info_members.png new file mode 100644 index 000000000..9f3ca1cd0 Binary files /dev/null and b/Telegram/Resources/icons/info_members.png differ diff --git a/Telegram/Resources/icons/info_members@2x.png b/Telegram/Resources/icons/info_members@2x.png new file mode 100644 index 000000000..e72085c31 Binary files /dev/null and b/Telegram/Resources/icons/info_members@2x.png differ diff --git a/Telegram/Resources/icons/info_notifications.png b/Telegram/Resources/icons/info_notifications.png new file mode 100644 index 000000000..651e78f2c Binary files /dev/null and b/Telegram/Resources/icons/info_notifications.png differ diff --git a/Telegram/Resources/icons/info_notifications@2x.png b/Telegram/Resources/icons/info_notifications@2x.png new file mode 100644 index 000000000..fecc98cef Binary files /dev/null and b/Telegram/Resources/icons/info_notifications@2x.png differ diff --git a/Telegram/Resources/icons/top_bar_call.png b/Telegram/Resources/icons/top_bar_call.png new file mode 100644 index 000000000..795149269 Binary files /dev/null and b/Telegram/Resources/icons/top_bar_call.png differ diff --git a/Telegram/Resources/icons/top_bar_call@2x.png b/Telegram/Resources/icons/top_bar_call@2x.png new file mode 100644 index 000000000..f15093923 Binary files /dev/null and b/Telegram/Resources/icons/top_bar_call@2x.png differ diff --git a/Telegram/Resources/icons/top_bar_profile.png b/Telegram/Resources/icons/top_bar_profile.png new file mode 100644 index 000000000..0d28dee1e Binary files /dev/null and b/Telegram/Resources/icons/top_bar_profile.png differ diff --git a/Telegram/Resources/icons/top_bar_profile@2x.png b/Telegram/Resources/icons/top_bar_profile@2x.png new file mode 100644 index 000000000..7bfdc3bcb Binary files /dev/null and b/Telegram/Resources/icons/top_bar_profile@2x.png differ diff --git a/Telegram/Resources/icons/top_bar_search.png b/Telegram/Resources/icons/top_bar_search.png new file mode 100644 index 000000000..cd1ac34e6 Binary files /dev/null and b/Telegram/Resources/icons/top_bar_search.png differ diff --git a/Telegram/Resources/icons/top_bar_search@2x.png b/Telegram/Resources/icons/top_bar_search@2x.png new file mode 100644 index 000000000..c1acb1ab3 Binary files /dev/null and b/Telegram/Resources/icons/top_bar_search@2x.png differ diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index c5e569340..40417aeb6 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -553,16 +553,13 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org "lng_profile_recent_actions" = "Recent actions"; "lng_profile_common_groups#one" = "{count} group in common"; "lng_profile_common_groups#other" = "{count} groups in common"; -"lng_profile_common_groups_section" = "Groups in common"; "lng_profile_participants_section" = "Members"; -"lng_profile_info_section" = "Info"; "lng_profile_mobile_number" = "Mobile:"; "lng_profile_username" = "Username:"; "lng_profile_link" = "Link:"; "lng_profile_bio" = "Bio:"; "lng_profile_add_contact" = "Add Contact"; "lng_profile_edit_contact" = "Edit"; -"lng_profile_enable_notifications" = "Notifications"; "lng_profile_clear_history" = "Clear history"; "lng_profile_delete_conversation" = "Delete conversation"; "lng_profile_clear_and_exit" = "Delete and exit"; @@ -576,7 +573,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org "lng_profile_unblock_user" = "Unblock user"; "lng_profile_block_bot" = "Stop and block bot"; "lng_profile_unblock_bot" = "Unblock bot"; -"lng_profile_send_message" = "Send Message"; "lng_profile_share_contact" = "Share Contact"; "lng_profile_invite_to_group" = "Add to Group"; "lng_profile_delete_contact" = "Delete"; @@ -589,7 +585,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org "lng_profile_sure_kick" = "Remove {user} from the group?"; "lng_profile_sure_kick_channel" = "Remove {user} from the channel?"; "lng_profile_loading" = "Loading..."; -"lng_profile_shared_media" = "Shared media"; "lng_profile_photos#one" = "{count} photo"; "lng_profile_photos#other" = "{count} photos"; "lng_profile_photos_header" = "Photos"; @@ -615,6 +610,30 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org "lng_profile_drop_area_subtitle_channel" = "to set it as a channel photo"; "lng_profile_top_bar_share_contact" = "Share"; +"lng_profile_info_section" = "Info"; +"lng_info_tab_media" = "Media"; +"lng_info_mobile_label" = "Mobile"; +"lng_info_username_label" = "Username"; +"lng_info_bio_label" = "Bio"; +"lng_info_link_label" = "Link"; +"lng_info_about_label" = "About"; +"lng_info_user_title" = "User Info"; +"lng_info_bot_title" = "Bot Info"; +"lng_info_group_title" = "Group Info"; +"lng_info_channel_title" = "Channel Info"; +"lng_profile_enable_notifications" = "Notifications"; +"lng_profile_send_message" = "Send Message"; +"lng_info_add_as_contact" = "Add as contact"; +"lng_profile_shared_media" = "Shared media"; +"lng_media_type_photos" = "Photos"; +"lng_media_type_videos" = "Videos"; +"lng_media_type_songs" = "Audio files"; +"lng_media_type_files" = "Files"; +"lng_media_type_audios" = "Voice messages"; +"lng_media_type_links" = "Shared links"; +"lng_media_type_rounds" = "Video messages"; +"lng_profile_common_groups_section" = "Groups in common"; + "lng_report_title" = "Report channel"; "lng_report_group_title" = "Report group"; "lng_report_bot_title" = "Report bot"; @@ -812,12 +831,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org "lng_attach_photo" = "Photo"; "lng_media_type" = "Media type"; -"lng_media_type_photos" = "Photos"; -"lng_media_type_videos" = "Videos"; -"lng_media_type_songs" = "Audio files"; -"lng_media_type_files" = "Files"; -"lng_media_type_audios" = "Voice messages"; -"lng_media_type_links" = "Shared links"; "lng_media_open_with" = "Open With"; "lng_media_download" = "Download"; diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index c5f6f6c37..756d54dc2 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -1928,15 +1928,26 @@ void ApiWrap::requestSharedMedia( auto filter = [&] { using Type = SharedMediaType; switch (type) { - case Type::Photo: return MTP_inputMessagesFilterPhotos(); - case Type::Video: return MTP_inputMessagesFilterVideo(); - case Type::MusicFile: return MTP_inputMessagesFilterMusic(); - case Type::File: return MTP_inputMessagesFilterDocument(); - case Type::VoiceFile: return MTP_inputMessagesFilterVoice(); - case Type::RoundVoiceFile: return MTP_inputMessagesFilterRoundVoice(); - case Type::GIF: return MTP_inputMessagesFilterGif(); - case Type::Link: return MTP_inputMessagesFilterUrl(); - case Type::ChatPhoto: return MTP_inputMessagesFilterChatPhotos(); + case Type::Photo: + return MTP_inputMessagesFilterPhotos(); + case Type::Video: + return MTP_inputMessagesFilterVideo(); + case Type::MusicFile: + return MTP_inputMessagesFilterMusic(); + case Type::File: + return MTP_inputMessagesFilterDocument(); + case Type::VoiceFile: + return MTP_inputMessagesFilterVoice(); + case Type::RoundVoiceFile: + return MTP_inputMessagesFilterRoundVoice(); + case Type::RoundFile: + return MTP_inputMessagesFilterRoundVideo(); + case Type::GIF: + return MTP_inputMessagesFilterGif(); + case Type::Link: + return MTP_inputMessagesFilterUrl(); + case Type::ChatPhoto: + return MTP_inputMessagesFilterChatPhotos(); } return MTP_inputMessagesFilterEmpty(); }(); diff --git a/Telegram/SourceFiles/base/variant.h b/Telegram/SourceFiles/base/variant.h index 02a005c19..1c1c2069c 100644 --- a/Telegram/SourceFiles/base/variant.h +++ b/Telegram/SourceFiles/base/variant.h @@ -38,4 +38,20 @@ inline const T *get_if(const variant *v) { return (v && v->template is()) ? &v->template get_unchecked() : nullptr; } +// Simplified visit +template +inline auto visit(Method &&method, const variant &value) { + return value.match(std::forward(method)); +} + +template +inline auto visit(Method &&method, variant &value) { + return value.match(std::forward(method)); +} + +template +inline auto visit(Method &&method, variant &&value) { + return value.match(std::forward(method)); +} + } // namespace base diff --git a/Telegram/SourceFiles/boxes/abstract_box.cpp b/Telegram/SourceFiles/boxes/abstract_box.cpp index 91dd88f7c..e90ce2ee6 100644 --- a/Telegram/SourceFiles/boxes/abstract_box.cpp +++ b/Telegram/SourceFiles/boxes/abstract_box.cpp @@ -424,7 +424,7 @@ void AbstractBox::keyPressEvent(QKeyEvent *e) { BoxLayerTitleShadow::BoxLayerTitleShadow(QWidget *parent) : Ui::PlainShadow(parent, st::boxLayerTitleShadow) { } -BoxContentDivider::BoxContentDivider(QWidget *parent) : TWidget(parent) { +BoxContentDivider::BoxContentDivider(QWidget *parent) : RpWidget(parent) { } int BoxContentDivider::resizeGetHeight(int newWidth) { diff --git a/Telegram/SourceFiles/boxes/abstract_box.h b/Telegram/SourceFiles/boxes/abstract_box.h index 178629615..3ea435e8d 100644 --- a/Telegram/SourceFiles/boxes/abstract_box.h +++ b/Telegram/SourceFiles/boxes/abstract_box.h @@ -290,7 +290,7 @@ public: }; -class BoxContentDivider : public TWidget { +class BoxContentDivider : public Ui::RpWidget { public: BoxContentDivider(QWidget *parent); diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp index 2abbde103..891fedfef 100644 --- a/Telegram/SourceFiles/facades.cpp +++ b/Telegram/SourceFiles/facades.cpp @@ -21,6 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "facades.h" #include "profile/profile_section_memento.h" +#include "info/info_memento.h" #include "core/click_handler_types.h" #include "media/media_clip_reader.h" #include "observer_peer.h" @@ -256,8 +257,17 @@ void autoplayMediaInlineAsync(const FullMsgId &msgId) { } void showPeerProfile(const PeerId &peer) { - if (auto main = App::main()) { - main->showWideSection(Profile::SectionMemento(App::peer(peer))); + //if (auto main = App::main()) { + // main->showWideSection(Profile::SectionMemento(App::peer(peer))); + //} + + if (auto window = App::wnd()) { + auto memento = Info::Memento(peer); + if (auto layer = memento.createLayer(window->controller())) { + window->showSpecialLayer(std::move(layer)); + } else { + App::main()->showWideSection(std::move(memento)); + } } } diff --git a/Telegram/SourceFiles/history/history_media_types.cpp b/Telegram/SourceFiles/history/history_media_types.cpp index ad69e985e..0de11b89c 100644 --- a/Telegram/SourceFiles/history/history_media_types.cpp +++ b/Telegram/SourceFiles/history/history_media_types.cpp @@ -1616,8 +1616,9 @@ void HistoryDocument::eraseFromOverview() { Storage::SharedMediaTypesMask HistoryDocument::sharedMediaTypes() const { using Type = Storage::SharedMediaType; if (_data->voice()) { - using Mask = Storage::SharedMediaTypesMask; - return Mask {}.added(Type::VoiceFile).added(Type::RoundVoiceFile); + return Storage::SharedMediaTypesMask{} + .added(Type::VoiceFile) + .added(Type::RoundVoiceFile); } else if (_data->song()) { if (_data->isMusic()) { return Type::MusicFile; @@ -2456,7 +2457,9 @@ int32 HistoryGif::addToOverview(AddToOverviewMethod method) { Storage::SharedMediaTypesMask HistoryGif::sharedMediaTypes() const { using Type = Storage::SharedMediaType; if (_data->isRoundVideo()) { - return Type::RoundVoiceFile; + return Storage::SharedMediaTypesMask{} + .added(Type::RoundFile) + .added(Type::RoundVoiceFile); } else if (_data->isGifv()) { return Type::GIF; } diff --git a/Telegram/SourceFiles/info/info.style b/Telegram/SourceFiles/info/info.style new file mode 100644 index 000000000..a68fd297c --- /dev/null +++ b/Telegram/SourceFiles/info/info.style @@ -0,0 +1,166 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org +*/ +using "basic.style"; + +using "boxes/boxes.style"; +using "ui/widgets/widgets.style"; + +infoScroll: ScrollArea(defaultScrollArea) { + bottomsh: 0px; + topsh: 0px; +} + +infoTopBarBackIcon: icon {{ "info_back", boxTitleCloseFg }}; +infoTopBarBackIconOver: icon {{ "info_back", boxTitleCloseFgOver }}; +infoTopBarHeight: boxLayerTitleHeight; +infoTopBarBack: IconButton(defaultIconButton) { + width: infoTopBarHeight; + height: infoTopBarHeight; + + icon: infoTopBarBackIcon; + iconOver: infoTopBarBackIconOver; + + rippleAreaPosition: point(6px, 6px); + rippleAreaSize: 44px; + ripple: RippleAnimation(defaultRippleAnimation) { + color: windowBgOver; + } +} + +infoLayerTopBarHeight: boxLayerTitleHeight; +infoLayerTopBarBackIcon: icon {{ "info_back", boxTitleCloseFg }}; +infoLayerTopBarBackIconOver: icon {{ "info_back", boxTitleCloseFgOver }}; +infoLayerTopBarBack: IconButton(infoTopBarBack) { + width: infoLayerTopBarHeight; + height: infoLayerTopBarHeight; + + icon: infoLayerTopBarBackIcon; + iconOver: infoLayerTopBarBackIconOver; +} +infoLayerTopBarCloseIcon: icon {{ "info_close", boxTitleCloseFg }}; +infoLayerTopBarCloseIconOver: icon {{ "info_close", boxTitleCloseFgOver }}; +infoLayerTopBarClose: IconButton(infoLayerTopBarBack) { + icon: infoLayerTopBarCloseIcon; + iconOver: infoLayerTopBarCloseIconOver; +} +infoLayerTopBar: InfoTopBar { + height: infoLayerTopBarHeight; + back: infoLayerTopBarBack; + title: boxTitle; + titlePosition: boxLayerTitlePosition; + bg: boxBg; +} + +infoMinimalWidth: 320px; +infoDesiredWidth: 360px; +infoMinimalLayerMargin: 48px; + +infoTabs: SettingsSlider(defaultTabsSlider) { + height: 55px; + barTop: 52px; + labelTop: 19px; +} + +infoProfilePhotoSize: 72px; +infoProfilePhotoLeft: 27px; +infoProfilePhotoTop: 22px; +infoProfilePhotoBottom: 22px; + +infoProfileNameLeft: 111px; +infoProfileNameRight: 20px; +infoProfileNameTop: 32px; +infoProfileNameLabel: FlatLabel(defaultFlatLabel) { + margin: margins(10px, 5px, 10px, 5px); + width: 160px; + maxHeight: 24px; + textFg: windowBoldFg; + style: TextStyle(defaultTextStyle) { + font: font(16px semibold); + linkFont: font(16px semibold); + linkFontOver: font(16px semibold underline); + } +} + +infoProfileStatusLeft: infoProfileNameLeft; +infoProfileStatusRight: infoProfileNameRight; +infoProfileStatusTop: 62px; +infoProfileStatusLabel: FlatLabel(infoProfileNameLabel) { + margin: margins(10px, 5px, 10px, 5px); + width: 160px; + maxHeight: 18px; + textFg: windowSubTextFg; + style: TextStyle(defaultTextStyle) { + font: normalFont; + linkFont: normalFont; + linkFontOver: normalFont; + } + palette: TextPalette(defaultTextPalette) { + linkFg: windowActiveTextFg; + } +} + +infoProfileToggleRight: 12px; +infoProfileToggleTop: 40px; + +infoProfileSkip: 12px; + +infoProfileLabeledPadding: margins(77px, 10px, 10px, 10px); +infoProfileSeparatorPadding: margins( + 73px, + infoProfileSkip, + 0px, + infoProfileSkip); + +infoIconFg: menuIconFg; +infoIconPosition: point(28px, 8px); +infoIconInformation: icon {{ "info_information", infoIconFg }}; +infoIconMembers: icon {{ "info_members", infoIconFg }}; +infoIconNotifications: icon {{ "info_notifications", infoIconFg }}; +infoIconActions: icon {{ "info_actions", infoIconFg }}; + +infoLabel: FlatLabel(defaultFlatLabel) { +} +infoLabeled: FlatLabel(defaultFlatLabel) { +} + +infoProfileButton: InfoProfileButton { + textFg: windowBoldFg; + textFgOver: windowBoldFgOver; + textBg: windowBg; + textBgOver: windowBgOver; + + font: semiboldFont; + + height: 22px; + padding: margins(80px, 8px, 8px, 8px); + + toggle: defaultMenuToggle; + toggleOver: defaultMenuToggleOver; + + ripple: defaultRippleAnimation; +} +infoNotificationsButton: InfoProfileButton(infoProfileButton) { + padding: margins(80px, 11px, 8px, 9px); +} +infoMainButton: InfoProfileButton(infoProfileButton) { + textFg: lightButtonFg; + textFgOver: lightButtonFgOver; +} diff --git a/Telegram/SourceFiles/info/info_common_groups_inner_widget.cpp b/Telegram/SourceFiles/info/info_common_groups_inner_widget.cpp new file mode 100644 index 000000000..48092280f --- /dev/null +++ b/Telegram/SourceFiles/info/info_common_groups_inner_widget.cpp @@ -0,0 +1,63 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org +*/ +#include "info/info_common_groups_inner_widget.h" + +#include "info/info_common_groups_widget.h" +#include "lang/lang_keys.h" +#include "styles/style_info.h" + +namespace Info { +namespace CommonGroups { + +InnerWidget::InnerWidget(QWidget *parent, not_null user) +: RpWidget(parent) +, _user(user) { + base::lambda launch = [this, &launch](int counter) { + QTimer::singleShot(500, this, [this, launch, counter] { + _rowsHeightFake += 300; + resizeToWidth(width(), _minHeight); + launch(counter - 1); + }); + }; + launch(10); +} + +void InnerWidget::visibleTopBottomUpdated( + int visibleTop, + int visibleBottom) { + _visibleTop = visibleTop; + _visibleBottom = visibleBottom; +} + +void InnerWidget::saveState(not_null memento) { +} + +void InnerWidget::restoreState(not_null memento) { +} + +int InnerWidget::resizeGetHeight(int newWidth) { + auto rowsHeight = _rowsHeightFake; + return qMax(rowsHeight, _minHeight); +} + +} // namespace CommonGroups +} // namespace Info + diff --git a/Telegram/SourceFiles/info/info_common_groups_inner_widget.h b/Telegram/SourceFiles/info/info_common_groups_inner_widget.h new file mode 100644 index 000000000..f868ba23a --- /dev/null +++ b/Telegram/SourceFiles/info/info_common_groups_inner_widget.h @@ -0,0 +1,65 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org +*/ +#pragma once + +#include +#include "ui/rp_widget.h" + +namespace Info { +namespace CommonGroups { + +class Memento; + +class InnerWidget final : public Ui::RpWidget { +public: + InnerWidget(QWidget *parent, not_null user); + + not_null user() const { + return _user; + } + + void resizeToWidth(int newWidth, int minHeight) { + _minHeight = minHeight; + return RpWidget::resizeToWidth(newWidth); + } + + void saveState(not_null memento); + void restoreState(not_null memento); + +protected: + int resizeGetHeight(int newWidth) override; + void visibleTopBottomUpdated( + int visibleTop, + int visibleBottom) override; + +private: + not_null _user; + + int _rowsHeightFake = 0; + int _visibleTop = 0; + int _visibleBottom = 0; + int _minHeight = 0; + +}; + +} // namespace CommonGroups +} // namespace Info + diff --git a/Telegram/SourceFiles/info/info_common_groups_widget.cpp b/Telegram/SourceFiles/info/info_common_groups_widget.cpp new file mode 100644 index 000000000..ac77ed70d --- /dev/null +++ b/Telegram/SourceFiles/info/info_common_groups_widget.cpp @@ -0,0 +1,92 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org +*/ +#include "info/info_common_groups_widget.h" + +#include "info/info_common_groups_inner_widget.h" +#include "ui/widgets/scroll_area.h" + +namespace Info { +namespace CommonGroups { + +object_ptr Memento::createWidget( + QWidget *parent, + Wrap wrap, + not_null controller, + const QRect &geometry) { + auto result = object_ptr( + parent, + wrap, + controller, + App::user(_userId)); + result->setInternalState(geometry, this); + return std::move(result); +} + +Widget::Widget( + QWidget *parent, + Wrap wrap, + not_null controller, + not_null user) +: ContentWidget(parent, wrap, controller) { + _inner = setInnerWidget(object_ptr(this, user)); +} + +not_null Widget::user() const { + return _inner->user(); +} + +bool Widget::showInternal(not_null memento) { + if (auto groupsMemento = dynamic_cast(memento.get())) { + if (groupsMemento->userId() == user()->bareId()) { + restoreState(groupsMemento); + return true; + } + } + return false; +} + +void Widget::setInternalState(const QRect &geometry, not_null memento) { + setGeometry(geometry); + myEnsureResized(this); + restoreState(memento); +} + +std::unique_ptr Widget::createMemento() { + auto result = std::make_unique(user()->bareId()); + saveState(result.get()); + return std::move(result); +} + +void Widget::saveState(not_null memento) { + memento->setScrollTop(scrollTopSave()); + _inner->saveState(memento); +} + +void Widget::restoreState(not_null memento) { + _inner->restoreState(memento); + auto scrollTop = memento->scrollTop(); + scrollTopRestore(memento->scrollTop()); + // TODO is setVisibleTopBottom called? +} + +} // namespace CommonGroups +} // namespace Info + diff --git a/Telegram/SourceFiles/info/info_common_groups_widget.h b/Telegram/SourceFiles/info/info_common_groups_widget.h new file mode 100644 index 000000000..ab742edc5 --- /dev/null +++ b/Telegram/SourceFiles/info/info_common_groups_widget.h @@ -0,0 +1,79 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org +*/ +#pragma once + +#include +#include "info/info_memento.h" + +namespace Info { +namespace CommonGroups { + +class InnerWidget; + +class Memento final : public ContentMemento { +public: + Memento(UserId userId) : _userId(userId) { + } + + object_ptr createWidget( + QWidget *parent, + Wrap wrap, + not_null controller, + const QRect &geometry) override; + + UserId userId() const { + return _userId; + } + +private: + UserId _userId = 0; + +}; + +class Widget final : public ContentWidget { +public: + Widget( + QWidget *parent, + Wrap wrap, + not_null controller, + not_null user); + + not_null user() const; + + bool showInternal( + not_null memento) override; + std::unique_ptr createMemento() override; + + void setInternalState( + const QRect &geometry, + not_null memento); + +private: + void saveState(not_null memento); + void restoreState(not_null memento); + + InnerWidget *_inner = nullptr; + +}; + +} // namespace CommonGroups +} // namespace Info + diff --git a/Telegram/SourceFiles/info/info_layer_wrap.cpp b/Telegram/SourceFiles/info/info_layer_wrap.cpp new file mode 100644 index 000000000..0788fc398 --- /dev/null +++ b/Telegram/SourceFiles/info/info_layer_wrap.cpp @@ -0,0 +1,164 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org +*/ +#include "info/info_layer_wrap.h" + +#include "info/info_memento.h" +#include "info/info_top_bar.h" +#include "ui/rp_widget.h" +#include "ui/widgets/buttons.h" +#include "window/section_widget.h" +#include "window/window_controller.h" +#include "window/main_window.h" +#include "styles/style_info.h" +#include "styles/style_settings.h" +#include "styles/style_window.h" +#include "styles/style_boxes.h" + +namespace Info { + +LayerWrap::LayerWrap( + not_null controller, + not_null memento) +: _topBar(createTopBar(controller, memento)) +, _content(createContent(controller, memento)) { + _content->desiredHeightValue() + | rpl::on_next([this](int height) { + _desiredHeight = height; + resizeToDesiredHeight(); + }) + | rpl::start(lifetime()); +} + +object_ptr LayerWrap::createTopBar( + not_null controller, + not_null memento) { + auto result = object_ptr( + this, + st::infoLayerTopBar); + result->addButton(object_ptr( + result.data(), + st::infoLayerTopBarClose)); + result->setTitle(TitleValue( + memento->section(), + App::peer(memento->peerId()))); + return result; +} + +object_ptr LayerWrap::createContent( + not_null controller, + not_null memento) { + return memento->content()->createWidget( + this, + Wrap::Layer, + controller, + controller->window()->rect()); +} + +void LayerWrap::showFinished() { +} + +void LayerWrap::parentResized() { + auto parentSize = parentWidget()->size(); + auto windowWidth = parentSize.width(); + auto newWidth = st::settingsMaxWidth; + auto newContentLeft = st::settingsMaxPadding; + if (windowWidth <= st::settingsMaxWidth) { + newWidth = windowWidth; + newContentLeft = st::settingsMinPadding; + if (windowWidth > st::windowMinWidth) { + // Width changes from st::windowMinWidth to st::settingsMaxWidth. + // Padding changes from st::settingsMinPadding to st::settingsMaxPadding. + newContentLeft += ((newWidth - st::windowMinWidth) * (st::settingsMaxPadding - st::settingsMinPadding)) / (st::settingsMaxWidth - st::windowMinWidth); + } + } else if (windowWidth < st::settingsMaxWidth + 2 * st::settingsMargin) { + newWidth = windowWidth - 2 * st::settingsMargin; + newContentLeft = st::settingsMinPadding; + if (windowWidth > st::windowMinWidth) { + // Width changes from st::windowMinWidth to st::settingsMaxWidth. + // Padding changes from st::settingsMinPadding to st::settingsMaxPadding. + newContentLeft += ((newWidth - st::windowMinWidth) * (st::settingsMaxPadding - st::settingsMinPadding)) / (st::settingsMaxWidth - st::windowMinWidth); + } + } + resizeToWidth(newWidth, newContentLeft); +} + +void LayerWrap::resizeToWidth(int newWidth, int newContentLeft) { + resize(newWidth, height()); + + _topBar->resizeToWidth(newWidth); + _topBar->moveToLeft(0, 0, newWidth); + + // Widget height depends on content height, so we + // resize it here, not in the resizeEvent() handler. + _content->resizeToWidth(newWidth); + _content->moveToLeft(0, _topBar->height(), newWidth); + + resizeToDesiredHeight(); +} + +void LayerWrap::resizeToDesiredHeight() { + if (!parentWidget()) return; + + auto parentSize = parentWidget()->size(); + auto windowWidth = parentSize.width(); + auto windowHeight = parentSize.height(); + auto maxHeight = _topBar->height() + _desiredHeight; + auto newHeight = maxHeight + st::boxRadius; + if (newHeight > windowHeight || width() >= windowWidth) { + newHeight = windowHeight; + } + + setRoundedCorners(newHeight < windowHeight); + + setGeometry((windowWidth - width()) / 2, (windowHeight - newHeight) / 2, width(), newHeight); + update(); +} + +void LayerWrap::setRoundedCorners(bool rounded) { + _roundedCorners = rounded; + setAttribute(Qt::WA_OpaquePaintEvent, !_roundedCorners); +} + +void LayerWrap::paintEvent(QPaintEvent *e) { + if (_roundedCorners) { + Painter p(this); + auto clip = e->rect(); + auto r = st::boxRadius; + auto parts = RectPart::None | 0; + if (clip.intersects({ 0, 0, width(), r })) { + parts |= RectPart::FullTop; + } + if (clip.intersects({ 0, height() - r, width(), r })) { + parts |= RectPart::FullBottom; + } + if (parts) { + App::roundRect( + p, + rect(), + st::boxBg, + BoxCorners, + nullptr, + parts); + } + } +} + +} // namespace Info diff --git a/Telegram/SourceFiles/info/info_layer_wrap.h b/Telegram/SourceFiles/info/info_layer_wrap.h new file mode 100644 index 000000000..2b499052b --- /dev/null +++ b/Telegram/SourceFiles/info/info_layer_wrap.h @@ -0,0 +1,68 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org +*/ +#pragma once + +#include "layerwidget.h" + +namespace Window { +class Controller; +} // namespace Window + +namespace Info { + +class Memento; +class ContentWidget; +class TopBar; + +class LayerWrap : public LayerWidget { +public: + LayerWrap( + not_null controller, + not_null memento); + + void showFinished() override; + void parentResized() override; + +protected: + void paintEvent(QPaintEvent *e) override; + + void setRoundedCorners(bool roundedCorners); + +private: + object_ptr createTopBar( + not_null controller, + not_null memento); + object_ptr createContent( + not_null controller, + not_null memento); + + void resizeToWidth(int newWidth, int newContentLeft); + void resizeToDesiredHeight(); + + object_ptr _topBar; + object_ptr _content; + + int _desiredHeight = 0; + bool _roundedCorners = false; + +}; + +} // namespace Info diff --git a/Telegram/SourceFiles/info/info_media_inner_widget.cpp b/Telegram/SourceFiles/info/info_media_inner_widget.cpp new file mode 100644 index 000000000..068e3356e --- /dev/null +++ b/Telegram/SourceFiles/info/info_media_inner_widget.cpp @@ -0,0 +1,62 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org +*/ +#include "info/info_media_inner_widget.h" + +namespace Info { +namespace Media { + +InnerWidget::InnerWidget( + QWidget *parent, + not_null peer, + Type type) +: RpWidget(parent) +, _peer(peer) +, _type(type) { + base::lambda launch = [this, &launch](int counter) { + QTimer::singleShot(500, this, [this, launch, counter] { + _rowsHeightFake += 300; + resizeToWidth(width(), _minHeight); + launch(counter - 1); + }); + }; + launch(10); +} + +void InnerWidget::visibleTopBottomUpdated( + int visibleTop, + int visibleBottom) { + _visibleTop = visibleTop; + _visibleBottom = visibleBottom; +} + +void InnerWidget::saveState(not_null memento) { +} + +void InnerWidget::restoreState(not_null memento) { +} + +int InnerWidget::resizeGetHeight(int newWidth) { + auto rowsHeight = _rowsHeightFake; + return qMax(rowsHeight, _minHeight); +} + +} // namespace Media +} // namespace Info diff --git a/Telegram/SourceFiles/info/info_media_inner_widget.h b/Telegram/SourceFiles/info/info_media_inner_widget.h new file mode 100644 index 000000000..eae591325 --- /dev/null +++ b/Telegram/SourceFiles/info/info_media_inner_widget.h @@ -0,0 +1,70 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org +*/ +#pragma once + +#include "ui/rp_widget.h" +#include "info/info_media_widget.h" + +namespace Info { +namespace Media { + +class InnerWidget final : public Ui::RpWidget { +public: + using Type = Widget::Type; + InnerWidget( + QWidget *parent, + not_null peer, + Type type); + + not_null peer() const { + return _peer; + } + Type type() const { + return _type; + } + + void resizeToWidth(int newWidth, int minHeight) { + _minHeight = minHeight; + return RpWidget::resizeToWidth(newWidth); + } + + void saveState(not_null memento); + void restoreState(not_null memento); + +protected: + int resizeGetHeight(int newWidth) override; + void visibleTopBottomUpdated( + int visibleTop, + int visibleBottom) override; + +private: + not_null _peer; + Type _type = Type::Photo; + + int _rowsHeightFake = 0; + int _visibleTop = 0; + int _visibleBottom = 0; + int _minHeight = 0; + +}; + +} // namespace Media +} // namespace Info diff --git a/Telegram/SourceFiles/info/info_media_widget.cpp b/Telegram/SourceFiles/info/info_media_widget.cpp new file mode 100644 index 000000000..b6ea88362 --- /dev/null +++ b/Telegram/SourceFiles/info/info_media_widget.cpp @@ -0,0 +1,95 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org +*/ +#include "info/info_media_widget.h" + +#include "info/info_media_inner_widget.h" +#include "ui/widgets/scroll_area.h" + +namespace Info { +namespace Media { + +object_ptr Memento::createWidget( + QWidget *parent, + Wrap wrap, + not_null controller, + const QRect &geometry) { + auto result = object_ptr( + parent, + wrap, + controller, + App::peer(_peerId), + _type); + result->setInternalState(geometry, this); + return std::move(result); +} + +Widget::Widget( + QWidget *parent, + Wrap wrap, + not_null controller, + not_null peer, + Type type) +: ContentWidget(parent, wrap, controller) { + _inner = setInnerWidget(object_ptr(this, peer, type)); +} + +not_null Widget::peer() const { + return _inner->peer(); +} + +Widget::Type Widget::type() const { + return _inner->type(); +} + +bool Widget::showInternal(not_null memento) { + if (auto mediaMemento = dynamic_cast(memento.get())) { + if (mediaMemento->peerId() == peer()->id) { + restoreState(mediaMemento); + return true; + } + } + return false; +} + +void Widget::setInternalState(const QRect &geometry, not_null memento) { + setGeometry(geometry); + myEnsureResized(this); + restoreState(memento); +} + +std::unique_ptr Widget::createMemento() { + auto result = std::make_unique(peer()->id, type()); + saveState(result.get()); + return std::move(result); +} + +void Widget::saveState(not_null memento) { + memento->setScrollTop(scrollTopSave()); + _inner->saveState(memento); +} + +void Widget::restoreState(not_null memento) { + _inner->restoreState(memento); + scrollTopRestore(memento->scrollTop()); +} + +} // namespace Media +} // namespace Info diff --git a/Telegram/SourceFiles/info/info_media_widget.h b/Telegram/SourceFiles/info/info_media_widget.h new file mode 100644 index 000000000..6fa19e163 --- /dev/null +++ b/Telegram/SourceFiles/info/info_media_widget.h @@ -0,0 +1,91 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org +*/ +#pragma once + +#include +#include "info/info_memento.h" +#include "storage/storage_shared_media.h" + +namespace Info { +namespace Media { + +class InnerWidget; + +class Memento final : public ContentMemento { +public: + using Type = Storage::SharedMediaType; + + Memento(PeerId peerId, Type type) + : _peerId(peerId) + , _type(type) { + } + + object_ptr createWidget( + QWidget *parent, + Wrap wrap, + not_null controller, + const QRect &geometry) override; + + PeerId peerId() const { + return _peerId; + } + Type type() const { + return _type; + } + +private: + PeerId _peerId = 0; + Type _type = Type::Photo; + +}; + +class Widget final : public ContentWidget { +public: + using Type = Memento::Type; + + Widget( + QWidget *parent, + Wrap wrap, + not_null controller, + not_null peer, + Type type); + + not_null peer() const; + Type type() const; + + bool showInternal( + not_null memento) override; + std::unique_ptr createMemento() override; + + void setInternalState( + const QRect &geometry, + not_null memento); + +private: + void saveState(not_null memento); + void restoreState(not_null memento); + + InnerWidget *_inner = nullptr; + +}; + +} // namespace Media +} // namespace Info diff --git a/Telegram/SourceFiles/info/info_memento.cpp b/Telegram/SourceFiles/info/info_memento.cpp new file mode 100644 index 000000000..2f1733b41 --- /dev/null +++ b/Telegram/SourceFiles/info/info_memento.cpp @@ -0,0 +1,227 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org +*/ +#include "info/info_memento.h" + +#include +#include "window/window_controller.h" +#include "ui/widgets/scroll_area.h" +#include "lang/lang_keys.h" +#include "info/info_profile_widget.h" +#include "info/info_media_widget.h" +#include "info/info_common_groups_widget.h" +#include "info/info_layer_wrap.h" +#include "info/info_narrow_wrap.h" +#include "info/info_side_wrap.h" +#include "styles/style_info.h" +#include "styles/style_profile.h" + +namespace Info { + +ContentWidget::ContentWidget( + QWidget *parent, + Wrap wrap, + not_null controller) +: RpWidget(parent) +, _controller(controller) +, _wrap(wrap) +, _scroll(this, st::infoScroll) { + setAttribute(Qt::WA_OpaquePaintEvent); +} + +void ContentWidget::resizeEvent(QResizeEvent *e) { + auto newScrollTop = _scroll->scrollTop() + _topDelta; + auto scrollGeometry = rect().marginsRemoved( + QMargins(0, _scrollTopSkip, 0, 0)); + if (_scroll->geometry() != scrollGeometry) { + _scroll->setGeometry(scrollGeometry); + _inner->setMinimumHeight(_scroll->height()); + _inner->resizeToWidth(_scroll->width()); + } + + if (!_scroll->isHidden()) { + if (_topDelta) { + _scroll->scrollToY(newScrollTop); + } + auto scrollTop = _scroll->scrollTop(); + _inner->setVisibleTopBottom(scrollTop, scrollTop + _scroll->height()); + } +} + +void ContentWidget::paintEvent(QPaintEvent *e) { + Painter p(this); + p.fillRect(e->rect(), (_wrap == Wrap::Layer) + ? st::boxBg + : st::profileBg); +} + +void ContentWidget::setGeometryWithTopMoved( + const QRect &newGeometry, + int topDelta) { + _topDelta = topDelta; + auto willBeResized = (size() != newGeometry.size()); + if (geometry() != newGeometry) { + setGeometry(newGeometry); + } + if (!willBeResized) { + QResizeEvent fake(size(), size()); + QApplication::sendEvent(this, &fake); + } + _topDelta = 0; +} + +Ui::RpWidget *ContentWidget::doSetInnerWidget( + object_ptr inner, + int scrollTopSkip) { + _inner = _scroll->setOwnedWidget(std::move(inner)); + _inner->move(0, 0); + + scrollTopValue() + | rpl::on_next([this, inner = _inner](int value) { + inner->setVisibleTopBottom( + value, + value + _scroll->height()); // TODO rpl::combine_latest + }) + | rpl::start(_inner->lifetime()); + return _inner; +} + +rpl::producer
ContentWidget::sectionRequest() const { + return rpl::never
(); +} + +rpl::producer ContentWidget::desiredHeightValue() const { + return _inner->desiredHeightValue() + | rpl::map([this](int value) { + return value + _scrollTopSkip; + }); +} + +rpl::producer ContentWidget::scrollTopValue() const { + return _scroll->scrollTopValue(); +} + +void ContentWidget::setWrap(Wrap wrap) { + _wrap = wrap; + update(); +} + +int ContentWidget::scrollTopSave() const { + return _scroll->scrollTop(); +} + +void ContentWidget::scrollTopRestore(int scrollTop) { + _scroll->scrollToY(scrollTop); +} + +bool ContentWidget::wheelEventFromFloatPlayer(QEvent *e) { + return _scroll->viewportEvent(e); +} + +QRect ContentWidget::rectForFloatPlayer() const { + return mapToGlobal(_scroll->geometry()); +} + +std::unique_ptr Memento::Default( + PeerId peerId, + Section section) { + switch (section.type()) { + case Section::Type::Profile: + return std::make_unique(peerId); + case Section::Type::Media: + return std::make_unique( + peerId, + section.mediaType()); + case Section::Type::CommonGroups: + Assert(peerIsUser(peerId)); + return std::make_unique( + peerToUser(peerId)); + } + Unexpected("Wrong section type in Info::Memento::Default()"); +} + +object_ptr Memento::createWidget( + QWidget *parent, + not_null controller, + const QRect &geometry) { + return object_ptr( + parent, + controller, + this); +} + +object_ptr Memento::createLayer( + not_null controller) { + auto layout = controller->computeColumnLayout(); + auto minimalWidthForLayer = st::infoMinimalWidth + + 2 * st::infoMinimalLayerMargin; + if (layout.bodyWidth < minimalWidthForLayer) { + return nullptr; + } + return object_ptr(controller, this); +} + +rpl::producer TitleValue( + const Section §ion, + not_null peer) { + return Lang::Viewer([&] { + switch (section.type()) { + case Section::Type::Profile: + if (auto user = peer->asUser()) { + return user->botInfo + ? lng_info_bot_title + : lng_info_user_title; + } else if (auto channel = peer->asChannel()) { + return channel->isMegagroup() + ? lng_info_group_title + : lng_info_channel_title; + } else if (peer->isChat()) { + return lng_info_group_title; + } + Unexpected("Bad peer type in Info::TitleValue()"); + + case Section::Type::Media: + switch (section.mediaType()) { + case Section::MediaType::Photo: + return lng_media_type_photos; + case Section::MediaType::Video: + return lng_media_type_videos; + case Section::MediaType::MusicFile: + return lng_media_type_songs; + case Section::MediaType::File: + return lng_media_type_files; + case Section::MediaType::VoiceFile: + return lng_media_type_audios; + case Section::MediaType::Link: + return lng_media_type_links; + case Section::MediaType::RoundFile: + return lng_media_type_rounds; + } + Unexpected("Bad media type in Info::TitleValue()"); + + case Section::Type::CommonGroups: + return lng_profile_common_groups_section; + + } + Unexpected("Bad section type in Info::TitleValue()"); + }()); +} + +} // namespace Info diff --git a/Telegram/SourceFiles/info/info_memento.h b/Telegram/SourceFiles/info/info_memento.h new file mode 100644 index 000000000..75fa8d058 --- /dev/null +++ b/Telegram/SourceFiles/info/info_memento.h @@ -0,0 +1,223 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org +*/ +#pragma once + +#include "window/section_memento.h" +#include "ui/rp_widget.h" + +namespace Storage { +enum class SharedMediaType : char; +} // namespace Storage + +namespace Ui { +class ScrollArea; +} // namespace Ui + +namespace Info { + +enum class Wrap { + Layer, + Narrow, + Side, +}; + +class Section final { +public: + enum class Type { + Profile, + Media, + CommonGroups, + }; + using MediaType = Storage::SharedMediaType; + + Section(Type type) : _type(type) { + Expects(type != Type::Media); + } + Section(MediaType mediaType) + : _type(Type::Media) + , _mediaType(mediaType) { + } + + Type type() const { + return _type; + } + MediaType mediaType() const { + Expects(_type == Type::Media); + return _mediaType; + } + +private: + Type _type; + Storage::SharedMediaType _mediaType; + +}; + +class ContentMemento; + +class ContentWidget : public Ui::RpWidget { +public: + ContentWidget( + QWidget *parent, + Wrap wrap, + not_null controller); + + virtual bool showInternal( + not_null memento) = 0; + virtual std::unique_ptr createMemento() = 0; + + virtual rpl::producer
sectionRequest() const; + + virtual void setWrap(Wrap wrap); + + rpl::producer desiredHeightValue() const override; + + virtual void setInnerFocus() { + _inner->setFocus(); + } + + // When resizing the widget with top edge moved up or down and we + // want to add this top movement to the scroll position, so inner + // content will not move. + void setGeometryWithTopMoved( + const QRect &newGeometry, + int topDelta); + + // Float player interface. + bool wheelEventFromFloatPlayer(QEvent *e); + QRect rectForFloatPlayer() const; + +protected: + template + Widget *setInnerWidget( + object_ptr inner, + int scrollTopSkip = 0) { + return static_cast( + doSetInnerWidget(std::move(inner), scrollTopSkip)); + } + + not_null controller() const { + return _controller; + } + Wrap wrap() const { + return _wrap; + } + + void resizeEvent(QResizeEvent *e) override; + void paintEvent(QPaintEvent *e) override; + + rpl::producer scrollTopValue() const; + int scrollTopSave() const; + void scrollTopRestore(int scrollTop); + +private: + RpWidget *doSetInnerWidget( + object_ptr inner, + int scrollTopSkip); + + not_null _controller; + Wrap _wrap = Wrap::Layer; + + int _scrollTopSkip = 0; + object_ptr _scroll; + Ui::RpWidget *_inner = nullptr; + + // Saving here topDelta in setGeometryWithTopMoved() to get it passed to resizeEvent(). + int _topDelta = 0; + +}; + +class ContentMemento { +public: + virtual object_ptr createWidget( + QWidget *parent, + Wrap wrap, + not_null controller, + const QRect &geometry) = 0; + + virtual ~ContentMemento() = default; + + void setScrollTop(int scrollTop) { + _scrollTop = scrollTop; + } + int scrollTop() const { + return _scrollTop; + } + +private: + int _scrollTop = 0; + +}; + +class Memento final : public Window::SectionMemento { +public: + Memento(PeerId peerId) + : Memento(peerId, Section::Type::Profile) { + } + Memento(PeerId peerId, Section section) + : Memento(peerId, section, Default(peerId, section)) { + } + Memento( + PeerId peerId, + Section section, + std::unique_ptr content) + : _peerId(peerId) + , _section(section) + , _content(std::move(content)) { + } + + object_ptr createWidget( + QWidget *parent, + not_null controller, + const QRect &geometry) override; + + object_ptr createLayer( + not_null controller) override; + + void setInner(std::unique_ptr content) { + _content = std::move(content); + } + not_null content() { + return _content.get(); + } + + PeerId peerId() const { + return _peerId; + } + Section section() const { + return _section; + } + +private: + static std::unique_ptr Default( + PeerId peerId, + Section section); + + PeerId _peerId = 0; + Section _section = Section::Type::Profile; + std::unique_ptr _content; + +}; + +rpl::producer TitleValue( + const Section §ion, + not_null peer); + +} // namespace Info diff --git a/Telegram/SourceFiles/info/info_narrow_wrap.cpp b/Telegram/SourceFiles/info/info_narrow_wrap.cpp new file mode 100644 index 000000000..620138535 --- /dev/null +++ b/Telegram/SourceFiles/info/info_narrow_wrap.cpp @@ -0,0 +1,158 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org +*/ +#include "info/info_narrow_wrap.h" + +#include +#include "info/info_profile_widget.h" +#include "info/info_media_widget.h" +#include "info/info_memento.h" +#include "ui/widgets/discrete_sliders.h" +#include "ui/widgets/shadow.h" +#include "lang/lang_keys.h" +#include "styles/style_info.h" +#include "styles/style_profile.h" + +namespace Info { + +NarrowWrap::NarrowWrap( + QWidget *parent, + not_null controller, + not_null memento) +: Window::SectionWidget(parent, controller) +, _peer(App::peer(memento->peerId())) { + setInternalState(geometry(), memento); +} + +void NarrowWrap::showInner(object_ptr inner) { + _inner = std::move(inner); + _inner->setGeometry(innerGeometry()); + _inner->show(); + + _desiredHeights.fire(desiredHeightForInner()); +} + +rpl::producer NarrowWrap::desiredHeightForInner() const { + return _inner->desiredHeightValue(); +} + +object_ptr NarrowWrap::createProfileWidget() { + auto result = object_ptr( + this, + Wrap::Narrow, + controller(), + _peer); + return result; +} + +object_ptr NarrowWrap::createMediaWidget() { + auto result = object_ptr( + this, + Wrap::Narrow, + controller(), + _peer, + Media::Widget::Type::Photo); + return result; +} + +QPixmap NarrowWrap::grabForShowAnimation( + const Window::SectionSlideParams ¶ms) { +// if (params.withTopBarShadow) _tabsShadow->hide(); + auto result = myGrab(this); +// if (params.withTopBarShadow) _tabsShadow->show(); + return result; +} + +void NarrowWrap::doSetInnerFocus() { + _inner->setInnerFocus(); +} + +bool NarrowWrap::showInternal( + not_null memento) { + if (auto infoMemento = dynamic_cast(memento.get())) { + if (infoMemento->peerId() == peer()->id) { + restoreState(infoMemento); + return true; + } + } + return false; +} + +void NarrowWrap::setInternalState( + const QRect &geometry, + not_null memento) { + setGeometry(geometry); + restoreState(memento); +} + +std::unique_ptr NarrowWrap::createMemento() { + auto result = std::make_unique(peer()->id); + saveState(result.get()); + return std::move(result); +} + +rpl::producer NarrowWrap::desiredHeight() const { + return + rpl::single(desiredHeightForInner()) + | rpl::then(_desiredHeights.events()) + | rpl::flatten_latest(); +} + +void NarrowWrap::saveState(not_null memento) { + memento->setInner(_inner->createMemento()); +} + +QRect NarrowWrap::innerGeometry() const { + return rect(); +} + +void NarrowWrap::restoreState(not_null memento) { + showInner(memento->content()->createWidget( + this, + Wrap::Narrow, + controller(), + innerGeometry())); +} + +void NarrowWrap::resizeEvent(QResizeEvent *e) { + if (_inner) { + _inner->setGeometry(innerGeometry()); + } +} + +void NarrowWrap::paintEvent(QPaintEvent *e) { + Painter p(this); + p.fillRect(e->rect(), st::profileBg); +} + +bool NarrowWrap::wheelEventFromFloatPlayer( + QEvent *e, + Window::Column myColumn, + Window::Column playerColumn) { + return _inner->wheelEventFromFloatPlayer(e); +} + +QRect NarrowWrap::rectForFloatPlayer( + Window::Column myColumn, + Window::Column playerColumn) const { + return _inner->rectForFloatPlayer(); +} + +} // namespace Info diff --git a/Telegram/SourceFiles/info/info_narrow_wrap.h b/Telegram/SourceFiles/info/info_narrow_wrap.h new file mode 100644 index 000000000..9d38ce069 --- /dev/null +++ b/Telegram/SourceFiles/info/info_narrow_wrap.h @@ -0,0 +1,112 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org +*/ +#pragma once + +#include +#include "window/section_widget.h" + +namespace Ui { +class PlainShadow; +class SettingsSlider; +} // namespace Ui + +namespace Info { +namespace Profile { +class Widget; +} // namespace Profile + +namespace Media { +class Widget; +} // namespace Media + +class Memento; +class ContentWidget; + +class NarrowWrap final : public Window::SectionWidget { +public: + NarrowWrap( + QWidget *parent, + not_null controller, + not_null memento); + + not_null peer() const { + return _peer; + } + PeerData *peerForDialogs() const override { + return _peer; + } + + bool hasTopBarShadow() const override { + return true; + } + + QPixmap grabForShowAnimation( + const Window::SectionSlideParams ¶ms) override; + + bool showInternal( + not_null memento) override; + std::unique_ptr createMemento() override; + + rpl::producer desiredHeight() const override; + + void setInternalState( + const QRect &geometry, + not_null memento); + + // Float player interface. + bool wheelEventFromFloatPlayer( + QEvent *e, + Window::Column myColumn, + Window::Column playerColumn) override; + QRect rectForFloatPlayer( + Window::Column myColumn, + Window::Column playerColumn) const override; + +protected: + void resizeEvent(QResizeEvent *e) override; + void paintEvent(QPaintEvent *e) override; + + void doSetInnerFocus() override; + +private: + void saveState(not_null memento); + void restoreState(not_null memento); + + QRect innerGeometry() const; + rpl::producer desiredHeightForInner() const; + + void showInner(object_ptr inner); + + object_ptr createProfileWidget(); + object_ptr createMediaWidget(); + + not_null _peer; + + object_ptr _tabsShadow = { nullptr }; + object_ptr _inner = { nullptr }; + + rpl::event_stream> _desiredHeights; + + rpl::lifetime _lifetime; + +}; + +} // namespace Info diff --git a/Telegram/SourceFiles/info/info_profile_inner_widget.cpp b/Telegram/SourceFiles/info/info_profile_inner_widget.cpp new file mode 100644 index 000000000..77f21ecd8 --- /dev/null +++ b/Telegram/SourceFiles/info/info_profile_inner_widget.cpp @@ -0,0 +1,211 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org +*/ +#include "info/info_profile_inner_widget.h" + +#include +#include "boxes/abstract_box.h" +#include "mainwidget.h" +#include "info/info_profile_widget.h" +#include "info/info_profile_lines.h" +#include "lang/lang_keys.h" +#include "styles/style_info.h" +#include "ui/widgets/buttons.h" +#include "ui/widgets/checkbox.h" + +namespace Info { +namespace Profile { + +InnerWidget::InnerWidget(QWidget *parent, not_null peer) +: RpWidget(parent) +, _peer(peer) +, _content(this) { + setupContent(); +} + +void InnerWidget::setupContent() { + auto hideDetails = (_peer->isChat() || _peer->isMegagroup()); + auto cover = _content->add(object_ptr(this, _peer)); + if (hideDetails) { + auto hiddenDetailsContent = setupDetailsContent(_content); + auto hiddenDetails = _content->add(object_ptr>( + this, + std::move(hiddenDetailsContent))); + cover->setHasToggle(true); + cover->toggled() + | rpl::on_next([=](bool expanded) { + hiddenDetails->toggleAnimated(expanded); + }) | rpl::start(_lifetime); + hiddenDetails->hideFast(); + } else { + _content->add(setupDetailsContent(_content)); + } + _content->add(object_ptr(this)); + + _content->heightValue() + | rpl::on_next([this](int height) { + TWidget::resizeToWidth(width()); + }) | rpl::start(_lifetime); +} + +object_ptr InnerWidget::setupDetailsContent( + RpWidget *parent) const { + auto result = object_ptr(parent); + + result->add(object_ptr(result)); + + auto skipPadding = QMargins(0, 0, 0, st::infoProfileSkip); + result->add(object_ptr>(result, skipPadding)); + + result->add(setupInfoLines(result)); + result->add(setupMuteToggle(result)); + if (auto user = _peer->asUser()) { + setupMainUserButtons(result, user); + } + + result->add(object_ptr>(result, skipPadding)); + + return result; +} + +object_ptr InnerWidget::setupMuteToggle( + RpWidget *parent) const { + auto result = object_ptr(parent); + auto button = result->add(object_ptr