mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-08-22 02:07:24 +00:00
Display hidden state in story albums.
This commit is contained in:
parent
677891d0ff
commit
953487bb65
11
.gitignore
vendored
11
.gitignore
vendored
@ -53,3 +53,14 @@ stage
|
|||||||
*.*~
|
*.*~
|
||||||
.idea/
|
.idea/
|
||||||
cmake-build-debug/
|
cmake-build-debug/
|
||||||
|
|
||||||
|
# Local configuration files
|
||||||
|
settings.local.json
|
||||||
|
*.local.json
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
.env.*.local
|
||||||
|
|
||||||
|
# Cursor IDE local settings (but keep .cursor/rules/)
|
||||||
|
.cursor/*
|
||||||
|
!.cursor/rules/
|
||||||
|
@ -1945,6 +1945,35 @@ void Stories::albumRename(
|
|||||||
}).send();
|
}).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Stories::albumDelete(not_null<PeerData*> peer, int id) {
|
||||||
|
_owner->session().api().request(MTPstories_DeleteAlbum(
|
||||||
|
peer->input,
|
||||||
|
MTP_int(id)
|
||||||
|
)).send();
|
||||||
|
|
||||||
|
auto &albums = _albums[peer->id];
|
||||||
|
auto current = albums.list.current();
|
||||||
|
current.erase(
|
||||||
|
ranges::remove(current, id, &StoryAlbum::id),
|
||||||
|
end(current));
|
||||||
|
albums.list = std::move(current);
|
||||||
|
|
||||||
|
const auto i = albums.sets.find(id);
|
||||||
|
if (i != end(albums.sets)) {
|
||||||
|
_owner->session().api().request(
|
||||||
|
base::take(i->second.requestId)).cancel();
|
||||||
|
for (const auto storyId : i->second.albumKnownInArchive) {
|
||||||
|
if (const auto story = lookup({ peer->id, storyId })) {
|
||||||
|
auto now = (*story)->albumIds();
|
||||||
|
if (now.remove(id)) {
|
||||||
|
(*story)->setAlbumIds(std::move(now));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
albums.sets.erase(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Stories::notifyAlbumUpdate(StoryAlbumUpdate &&update) {
|
void Stories::notifyAlbumUpdate(StoryAlbumUpdate &&update) {
|
||||||
const auto peerId = update.peer->id;
|
const auto peerId = update.peer->id;
|
||||||
const auto i = _albums.find(peerId);
|
const auto i = _albums.find(peerId);
|
||||||
|
@ -235,6 +235,7 @@ public:
|
|||||||
const QString &title,
|
const QString &title,
|
||||||
Fn<void(StoryAlbum)> done,
|
Fn<void(StoryAlbum)> done,
|
||||||
Fn<void(QString)> fail);
|
Fn<void(QString)> fail);
|
||||||
|
void albumDelete(not_null<PeerData*> peer, int id);
|
||||||
void notifyAlbumUpdate(StoryAlbumUpdate &&update);
|
void notifyAlbumUpdate(StoryAlbumUpdate &&update);
|
||||||
[[nodiscard]] rpl::producer<StoryAlbumUpdate> albumUpdates() const;
|
[[nodiscard]] rpl::producer<StoryAlbumUpdate> albumUpdates() const;
|
||||||
|
|
||||||
|
@ -367,7 +367,12 @@ bool Story::pinnedToTop() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Story::setInProfile(bool value) {
|
void Story::setInProfile(bool value) {
|
||||||
_inProfile = value;
|
if (_inProfile != value) {
|
||||||
|
_inProfile = value;
|
||||||
|
if (const auto item = _peer->owner().stories().lookupItem(this)) {
|
||||||
|
item->setStoryInProfile(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Story::inProfile() const {
|
bool Story::inProfile() const {
|
||||||
|
@ -356,6 +356,8 @@ enum class MessageFlag : uint64 {
|
|||||||
|
|
||||||
StarsPaidSuggested = (1ULL << 52),
|
StarsPaidSuggested = (1ULL << 52),
|
||||||
TonPaidSuggested = (1ULL << 53),
|
TonPaidSuggested = (1ULL << 53),
|
||||||
|
|
||||||
|
StoryInProfile = (1ULL << 54),
|
||||||
};
|
};
|
||||||
inline constexpr bool is_flag_type(MessageFlag) { return true; }
|
inline constexpr bool is_flag_type(MessageFlag) { return true; }
|
||||||
using MessageFlags = base::flags<MessageFlag>;
|
using MessageFlags = base::flags<MessageFlag>;
|
||||||
|
@ -1634,6 +1634,17 @@ void HistoryItem::setIsPinned(bool pinned) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HistoryItem::setStoryInProfile(bool inProfile) {
|
||||||
|
if (storyInProfile() == inProfile) {
|
||||||
|
return;
|
||||||
|
} else if (inProfile) {
|
||||||
|
_flags |= MessageFlag::StoryInProfile;
|
||||||
|
} else {
|
||||||
|
_flags &= ~MessageFlag::StoryInProfile;
|
||||||
|
}
|
||||||
|
_history->owner().notifyItemDataChange(this);
|
||||||
|
}
|
||||||
|
|
||||||
void HistoryItem::returnSavedMedia() {
|
void HistoryItem::returnSavedMedia() {
|
||||||
if (!isEditingMedia()) {
|
if (!isEditingMedia()) {
|
||||||
return;
|
return;
|
||||||
@ -2014,6 +2025,11 @@ void HistoryItem::setStoryFields(not_null<Data::Story*> story) {
|
|||||||
} else {
|
} else {
|
||||||
_flags &= ~MessageFlag::Pinned;
|
_flags &= ~MessageFlag::Pinned;
|
||||||
}
|
}
|
||||||
|
if (story->inProfile()) {
|
||||||
|
_flags |= MessageFlag::StoryInProfile;
|
||||||
|
} else {
|
||||||
|
_flags &= ~MessageFlag::StoryInProfile;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryItem::applyEdition(const MTPDmessageService &message) {
|
void HistoryItem::applyEdition(const MTPDmessageService &message) {
|
||||||
|
@ -235,6 +235,9 @@ public:
|
|||||||
[[nodiscard]] bool invertMedia() const {
|
[[nodiscard]] bool invertMedia() const {
|
||||||
return _flags & MessageFlag::InvertMedia;
|
return _flags & MessageFlag::InvertMedia;
|
||||||
}
|
}
|
||||||
|
[[nodiscard]] bool storyInProfile() const {
|
||||||
|
return _flags & MessageFlag::StoryInProfile;
|
||||||
|
}
|
||||||
[[nodiscard]] bool unread(not_null<Data::Thread*> thread) const;
|
[[nodiscard]] bool unread(not_null<Data::Thread*> thread) const;
|
||||||
[[nodiscard]] bool showNotification() const;
|
[[nodiscard]] bool showNotification() const;
|
||||||
void markClientSideAsRead();
|
void markClientSideAsRead();
|
||||||
@ -250,6 +253,7 @@ public:
|
|||||||
void markMediaAndMentionRead();
|
void markMediaAndMentionRead();
|
||||||
bool markContentsRead(bool fromThisClient = false);
|
bool markContentsRead(bool fromThisClient = false);
|
||||||
void setIsPinned(bool isPinned);
|
void setIsPinned(bool isPinned);
|
||||||
|
void setStoryInProfile(bool inProfile);
|
||||||
|
|
||||||
// For edit media in history_message.
|
// For edit media in history_message.
|
||||||
void returnSavedMedia();
|
void returnSavedMedia();
|
||||||
|
@ -588,10 +588,6 @@ void TopBar::setStories(rpl::producer<Dialogs::Stories::Content> content) {
|
|||||||
updateControlsVisibility(anim::type::instant);
|
updateControlsVisibility(anim::type::instant);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TopBar::setStoriesArchive(bool archive) {
|
|
||||||
_storiesArchive = archive;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TopBar::setSelectedItems(SelectedItems &&items) {
|
void TopBar::setSelectedItems(SelectedItems &&items) {
|
||||||
auto wasSelectionMode = selectionMode();
|
auto wasSelectionMode = selectionMode();
|
||||||
_selectedItems = std::move(items);
|
_selectedItems = std::move(items);
|
||||||
@ -628,10 +624,19 @@ void TopBar::updateSelectionState() {
|
|||||||
_canDelete = computeCanDelete();
|
_canDelete = computeCanDelete();
|
||||||
_canForward = computeCanForward();
|
_canForward = computeCanForward();
|
||||||
_canUnpinStories = computeCanUnpinStories();
|
_canUnpinStories = computeCanUnpinStories();
|
||||||
|
_canToggleStoryPin = computeCanToggleStoryPin();
|
||||||
|
_allStoriesInProfile = computeAllStoriesInProfile();
|
||||||
_selectionText->entity()->setValue(generateSelectedText());
|
_selectionText->entity()->setValue(generateSelectedText());
|
||||||
_delete->toggle(_canDelete, anim::type::instant);
|
_delete->toggle(_canDelete, anim::type::instant);
|
||||||
_forward->toggle(_canForward, anim::type::instant);
|
_forward->toggle(_canForward, anim::type::instant);
|
||||||
_toggleStoryInProfile->toggle(_canToggleStoryPin, anim::type::instant);
|
_toggleStoryInProfile->toggle(_canToggleStoryPin, anim::type::instant);
|
||||||
|
_toggleStoryInProfile->entity()->setIconOverride(
|
||||||
|
(_allStoriesInProfile
|
||||||
|
? &_st.storiesArchive.icon
|
||||||
|
: &_st.storiesSave.icon),
|
||||||
|
(_allStoriesInProfile
|
||||||
|
? &_st.storiesArchive.iconOver
|
||||||
|
: &_st.storiesSave.iconOver));
|
||||||
_toggleStoryPin->toggle(_canToggleStoryPin, anim::type::instant);
|
_toggleStoryPin->toggle(_canToggleStoryPin, anim::type::instant);
|
||||||
_toggleStoryPin->entity()->setIconOverride(
|
_toggleStoryPin->entity()->setIconOverride(
|
||||||
_canUnpinStories ? &_st.storiesUnpin.icon : nullptr,
|
_canUnpinStories ? &_st.storiesUnpin.icon : nullptr,
|
||||||
@ -652,6 +657,7 @@ void TopBar::createSelectionControls() {
|
|||||||
_canForward = computeCanForward();
|
_canForward = computeCanForward();
|
||||||
_canUnpinStories = computeCanUnpinStories();
|
_canUnpinStories = computeCanUnpinStories();
|
||||||
_canToggleStoryPin = computeCanToggleStoryPin();
|
_canToggleStoryPin = computeCanToggleStoryPin();
|
||||||
|
_allStoriesInProfile = computeAllStoriesInProfile();
|
||||||
_cancelSelection = wrap(Ui::CreateChild<Ui::FadeWrap<Ui::IconButton>>(
|
_cancelSelection = wrap(Ui::CreateChild<Ui::FadeWrap<Ui::IconButton>>(
|
||||||
this,
|
this,
|
||||||
object_ptr<Ui::IconButton>(this, _st.mediaCancel),
|
object_ptr<Ui::IconButton>(this, _st.mediaCancel),
|
||||||
@ -710,16 +716,18 @@ void TopBar::createSelectionControls() {
|
|||||||
this,
|
this,
|
||||||
object_ptr<Ui::IconButton>(
|
object_ptr<Ui::IconButton>(
|
||||||
this,
|
this,
|
||||||
_storiesArchive ? _st.storiesSave : _st.storiesArchive),
|
_allStoriesInProfile ? _st.storiesArchive : _st.storiesSave),
|
||||||
st::infoTopBarScale));
|
st::infoTopBarScale));
|
||||||
registerToggleControlCallback(
|
registerToggleControlCallback(
|
||||||
_toggleStoryInProfile.data(),
|
_toggleStoryInProfile.data(),
|
||||||
[this] { return selectionMode() && _canToggleStoryPin; });
|
[this] { return selectionMode() && _canToggleStoryPin; });
|
||||||
_toggleStoryInProfile->setDuration(st::infoTopBarDuration);
|
_toggleStoryInProfile->setDuration(st::infoTopBarDuration);
|
||||||
_toggleStoryInProfile->entity()->clicks(
|
_toggleStoryInProfile->entity()->clicks(
|
||||||
) | rpl::map_to(
|
) | rpl::map([=] {
|
||||||
SelectionAction::ToggleStoryInProfile
|
return _allStoriesInProfile
|
||||||
) | rpl::start_to_stream(
|
? SelectionAction::ToggleStoryToArchive
|
||||||
|
: SelectionAction::ToggleStoryToProfile;
|
||||||
|
}) | rpl::start_to_stream(
|
||||||
_selectionActionRequests,
|
_selectionActionRequests,
|
||||||
_cancelSelection->lifetime());
|
_cancelSelection->lifetime());
|
||||||
_toggleStoryInProfile->entity()->setVisible(_canToggleStoryPin);
|
_toggleStoryInProfile->entity()->setVisible(_canToggleStoryPin);
|
||||||
@ -769,6 +777,12 @@ bool TopBar::computeCanToggleStoryPin() const {
|
|||||||
&SelectedItem::canToggleStoryPin);
|
&SelectedItem::canToggleStoryPin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TopBar::computeAllStoriesInProfile() const {
|
||||||
|
return ranges::all_of(
|
||||||
|
_selectedItems.list,
|
||||||
|
&SelectedItem::storyInProfile);
|
||||||
|
}
|
||||||
|
|
||||||
Ui::StringWithNumbers TopBar::generateSelectedText() const {
|
Ui::StringWithNumbers TopBar::generateSelectedText() const {
|
||||||
return _selectedItems.title(_selectedItems.list.size());
|
return _selectedItems.title(_selectedItems.list.size());
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,6 @@ public:
|
|||||||
|
|
||||||
void setTitle(TitleDescriptor descriptor);
|
void setTitle(TitleDescriptor descriptor);
|
||||||
void setStories(rpl::producer<Dialogs::Stories::Content> content);
|
void setStories(rpl::producer<Dialogs::Stories::Content> content);
|
||||||
void setStoriesArchive(bool archive);
|
|
||||||
void enableBackButton();
|
void enableBackButton();
|
||||||
void highlight();
|
void highlight();
|
||||||
|
|
||||||
@ -131,6 +130,7 @@ private:
|
|||||||
[[nodiscard]] bool computeCanForward() const;
|
[[nodiscard]] bool computeCanForward() const;
|
||||||
[[nodiscard]] bool computeCanUnpinStories() const;
|
[[nodiscard]] bool computeCanUnpinStories() const;
|
||||||
[[nodiscard]] bool computeCanToggleStoryPin() const;
|
[[nodiscard]] bool computeCanToggleStoryPin() const;
|
||||||
|
[[nodiscard]] bool computeAllStoriesInProfile() const;
|
||||||
void updateSelectionState();
|
void updateSelectionState();
|
||||||
void createSelectionControls();
|
void createSelectionControls();
|
||||||
|
|
||||||
@ -178,7 +178,7 @@ private:
|
|||||||
bool _canForward = false;
|
bool _canForward = false;
|
||||||
bool _canToggleStoryPin = false;
|
bool _canToggleStoryPin = false;
|
||||||
bool _canUnpinStories = false;
|
bool _canUnpinStories = false;
|
||||||
bool _storiesArchive = false;
|
bool _allStoriesInProfile = false;
|
||||||
QPointer<Ui::FadeWrap<Ui::IconButton>> _cancelSelection;
|
QPointer<Ui::FadeWrap<Ui::IconButton>> _cancelSelection;
|
||||||
QPointer<Ui::FadeWrap<Ui::LabelWithNumbers>> _selectionText;
|
QPointer<Ui::FadeWrap<Ui::LabelWithNumbers>> _selectionText;
|
||||||
QPointer<Ui::FadeWrap<Ui::IconButton>> _forward;
|
QPointer<Ui::FadeWrap<Ui::IconButton>> _forward;
|
||||||
|
@ -657,8 +657,6 @@ void WrapWidget::finishShowContent() {
|
|||||||
.subtitle = _content->subtitle(),
|
.subtitle = _content->subtitle(),
|
||||||
});
|
});
|
||||||
_topBar->setStories(_content->titleStories());
|
_topBar->setStories(_content->titleStories());
|
||||||
_topBar->setStoriesArchive(
|
|
||||||
_controller->key().storiesAlbumId() == Stories::ArchiveId());
|
|
||||||
}
|
}
|
||||||
_desiredHeights.fire(desiredHeightForContent());
|
_desiredHeights.fire(desiredHeightForContent());
|
||||||
_desiredShadowVisibilities.fire(_content->desiredShadowVisibility());
|
_desiredShadowVisibilities.fire(_content->desiredShadowVisibility());
|
||||||
@ -787,7 +785,6 @@ bool WrapWidget::showInternal(
|
|||||||
&& (params.way == Window::SectionShow::Way::ClearStack);
|
&& (params.way == Window::SectionShow::Way::ClearStack);
|
||||||
if (_controller->validateMementoPeer(content)) {
|
if (_controller->validateMementoPeer(content)) {
|
||||||
if (!skipInternal && _content->showInternal(content)) {
|
if (!skipInternal && _content->showInternal(content)) {
|
||||||
highlightTopBar();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,7 @@ struct SelectedItem {
|
|||||||
bool canForward = false;
|
bool canForward = false;
|
||||||
bool canToggleStoryPin = false;
|
bool canToggleStoryPin = false;
|
||||||
bool canUnpinStory = false;
|
bool canUnpinStory = false;
|
||||||
|
bool storyInProfile = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SelectedItems {
|
struct SelectedItems {
|
||||||
@ -80,7 +81,8 @@ enum class SelectionAction {
|
|||||||
Forward,
|
Forward,
|
||||||
Delete,
|
Delete,
|
||||||
ToggleStoryPin,
|
ToggleStoryPin,
|
||||||
ToggleStoryInProfile,
|
ToggleStoryToProfile,
|
||||||
|
ToggleStoryToArchive,
|
||||||
};
|
};
|
||||||
|
|
||||||
class WrapWidget final : public Window::SectionWidget {
|
class WrapWidget final : public Window::SectionWidget {
|
||||||
|
@ -32,6 +32,7 @@ struct ListItemSelectionData {
|
|||||||
bool canForward = false;
|
bool canForward = false;
|
||||||
bool canToggleStoryPin = false;
|
bool canToggleStoryPin = false;
|
||||||
bool canUnpinStory = false;
|
bool canUnpinStory = false;
|
||||||
|
bool storyInProfile = false;
|
||||||
|
|
||||||
friend inline bool operator==(
|
friend inline bool operator==(
|
||||||
ListItemSelectionData,
|
ListItemSelectionData,
|
||||||
|
@ -58,6 +58,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
#include "media/player/media_player_instance.h"
|
#include "media/player/media_player_instance.h"
|
||||||
#include "boxes/delete_messages_box.h"
|
#include "boxes/delete_messages_box.h"
|
||||||
#include "boxes/peer_list_controllers.h"
|
#include "boxes/peer_list_controllers.h"
|
||||||
|
#include "boxes/sticker_set_box.h" // StickerPremiumMark
|
||||||
#include "core/file_utilities.h"
|
#include "core/file_utilities.h"
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
#include "ui/toast/toast.h"
|
#include "ui/toast/toast.h"
|
||||||
@ -66,6 +67,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
#include "styles/style_layers.h"
|
#include "styles/style_layers.h"
|
||||||
#include "styles/style_menu_icons.h"
|
#include "styles/style_menu_icons.h"
|
||||||
#include "styles/style_chat.h"
|
#include "styles/style_chat.h"
|
||||||
|
#include "styles/style_credits.h" // giftBoxHiddenMark
|
||||||
|
|
||||||
#include <QtWidgets/QApplication>
|
#include <QtWidgets/QApplication>
|
||||||
#include <QtGui/QClipboard>
|
#include <QtGui/QClipboard>
|
||||||
@ -152,7 +154,11 @@ ListWidget::ListWidget(
|
|||||||
_provider->type(),
|
_provider->type(),
|
||||||
[=] { scrollDateCheck(); },
|
[=] { scrollDateCheck(); },
|
||||||
[=] { scrollDateHide(); }))
|
[=] { scrollDateHide(); }))
|
||||||
, _storiesAddToAlbumId(controller->storiesAddToAlbumId()) {
|
, _storiesAddToAlbumId(controller->storiesAddToAlbumId())
|
||||||
|
, _hiddenMark(std::make_unique<StickerPremiumMark>(
|
||||||
|
&_controller->session(),
|
||||||
|
st::giftBoxHiddenMark,
|
||||||
|
RectPart::Center)) {
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,8 +318,11 @@ void ListWidget::selectionAction(SelectionAction action) {
|
|||||||
case SelectionAction::Clear: clearSelected(); return;
|
case SelectionAction::Clear: clearSelected(); return;
|
||||||
case SelectionAction::Forward: forwardSelected(); return;
|
case SelectionAction::Forward: forwardSelected(); return;
|
||||||
case SelectionAction::Delete: deleteSelected(); return;
|
case SelectionAction::Delete: deleteSelected(); return;
|
||||||
case SelectionAction::ToggleStoryInProfile:
|
case SelectionAction::ToggleStoryToProfile:
|
||||||
toggleStoryInProfileSelected();
|
toggleStoryInProfileSelected(true);
|
||||||
|
return;
|
||||||
|
case SelectionAction::ToggleStoryToArchive:
|
||||||
|
toggleStoryInProfileSelected(false);
|
||||||
return;
|
return;
|
||||||
case SelectionAction::ToggleStoryPin: toggleStoryPinSelected(); return;
|
case SelectionAction::ToggleStoryPin: toggleStoryPinSelected(); return;
|
||||||
}
|
}
|
||||||
@ -395,6 +404,7 @@ auto ListWidget::collectSelectedItems() const -> SelectedItems {
|
|||||||
result.canForward = selection.canForward;
|
result.canForward = selection.canForward;
|
||||||
result.canToggleStoryPin = selection.canToggleStoryPin;
|
result.canToggleStoryPin = selection.canToggleStoryPin;
|
||||||
result.canUnpinStory = selection.canUnpinStory;
|
result.canUnpinStory = selection.canUnpinStory;
|
||||||
|
result.storyInProfile = selection.storyInProfile;
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
auto transformation = [&](const auto &item) {
|
auto transformation = [&](const auto &item) {
|
||||||
@ -527,6 +537,10 @@ bool ListWidget::itemVisible(not_null<const BaseLayout*> item) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
not_null<StickerPremiumMark*> ListWidget::hiddenMark() {
|
||||||
|
return _hiddenMark.get();
|
||||||
|
}
|
||||||
|
|
||||||
QString ListWidget::tooltipText() const {
|
QString ListWidget::tooltipText() const {
|
||||||
if (const auto link = ClickHandler::getActive()) {
|
if (const auto link = ClickHandler::getActive()) {
|
||||||
return link->tooltip();
|
return link->tooltip();
|
||||||
@ -1020,6 +1034,11 @@ void ListWidget::showContextMenu(
|
|||||||
return !item.second.canToggleStoryPin;
|
return !item.second.canToggleStoryPin;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
const auto allInProfile = [&] {
|
||||||
|
return ranges::all_of(_selected, [](auto &&item) {
|
||||||
|
return item.second.storyInProfile;
|
||||||
|
});
|
||||||
|
};
|
||||||
const auto canUnpinStoryAll = [&] {
|
const auto canUnpinStoryAll = [&] {
|
||||||
return ranges::any_of(_selected, [](auto &&item) {
|
return ranges::any_of(_selected, [](auto &&item) {
|
||||||
return item.second.canUnpinStory;
|
return item.second.canUnpinStory;
|
||||||
@ -1125,13 +1144,14 @@ void ListWidget::showContextMenu(
|
|||||||
}
|
}
|
||||||
if (overSelected == SelectionState::OverSelectedItems) {
|
if (overSelected == SelectionState::OverSelectedItems) {
|
||||||
if (canToggleStoryPinAll()) {
|
if (canToggleStoryPinAll()) {
|
||||||
const auto albumId = _controller->storiesAlbumId();
|
const auto toProfile = !allInProfile();
|
||||||
const auto toProfile = (albumId == Stories::ArchiveId());
|
|
||||||
_contextMenu->addAction(
|
_contextMenu->addAction(
|
||||||
(toProfile
|
(toProfile
|
||||||
? tr::lng_mediaview_save_to_profile
|
? tr::lng_mediaview_save_to_profile
|
||||||
: tr::lng_archived_add)(tr::now),
|
: tr::lng_archived_add)(tr::now),
|
||||||
crl::guard(this, [this] { toggleStoryInProfileSelected(); }),
|
crl::guard(this, [=] {
|
||||||
|
toggleStoryInProfileSelected(toProfile);
|
||||||
|
}),
|
||||||
(toProfile
|
(toProfile
|
||||||
? &st::menuIconStoriesSave
|
? &st::menuIconStoriesSave
|
||||||
: &st::menuIconStoriesArchive));
|
: &st::menuIconStoriesArchive));
|
||||||
@ -1177,14 +1197,15 @@ void ListWidget::showContextMenu(
|
|||||||
item,
|
item,
|
||||||
FullSelection);
|
FullSelection);
|
||||||
if (selectionData.canToggleStoryPin) {
|
if (selectionData.canToggleStoryPin) {
|
||||||
const auto albumId = _controller->storiesAlbumId();
|
const auto toProfile = !selectionData.storyInProfile;
|
||||||
const auto toProfile = (albumId == Stories::ArchiveId());
|
|
||||||
_contextMenu->addAction(
|
_contextMenu->addAction(
|
||||||
(toProfile
|
(toProfile
|
||||||
? tr::lng_mediaview_save_to_profile
|
? tr::lng_mediaview_save_to_profile
|
||||||
: tr::lng_mediaview_archive_story)(tr::now),
|
: tr::lng_mediaview_archive_story)(tr::now),
|
||||||
crl::guard(this, [=] {
|
crl::guard(this, [=] {
|
||||||
toggleStoryInProfile({ 1, globalId.itemId });
|
toggleStoryInProfile(
|
||||||
|
{ 1, globalId.itemId },
|
||||||
|
toProfile);
|
||||||
}),
|
}),
|
||||||
(toProfile
|
(toProfile
|
||||||
? &st::menuIconStoriesSave
|
? &st::menuIconStoriesSave
|
||||||
@ -1317,10 +1338,11 @@ void ListWidget::deleteSelected() {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::toggleStoryInProfileSelected() {
|
void ListWidget::toggleStoryInProfileSelected(bool toProfile) {
|
||||||
toggleStoryInProfile(collectSelectedIds(), crl::guard(this, [=] {
|
toggleStoryInProfile(
|
||||||
clearSelected();
|
collectSelectedIds(),
|
||||||
}));
|
toProfile,
|
||||||
|
crl::guard(this, [=] { clearSelected(); }));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::toggleStoryPinSelected() {
|
void ListWidget::toggleStoryPinSelected() {
|
||||||
@ -1335,6 +1357,7 @@ void ListWidget::toggleStoryPinSelected() {
|
|||||||
|
|
||||||
void ListWidget::toggleStoryInProfile(
|
void ListWidget::toggleStoryInProfile(
|
||||||
MessageIdsList &&items,
|
MessageIdsList &&items,
|
||||||
|
bool toProfile,
|
||||||
Fn<void()> confirmed) {
|
Fn<void()> confirmed) {
|
||||||
auto list = std::vector<FullStoryId>();
|
auto list = std::vector<FullStoryId>();
|
||||||
for (const auto &id : items) {
|
for (const auto &id : items) {
|
||||||
@ -1347,8 +1370,6 @@ void ListWidget::toggleStoryInProfile(
|
|||||||
}
|
}
|
||||||
const auto channel = peerIsChannel(list.front().peer);
|
const auto channel = peerIsChannel(list.front().peer);
|
||||||
const auto count = int(list.size());
|
const auto count = int(list.size());
|
||||||
const auto albumId = _controller->storiesAlbumId();
|
|
||||||
const auto toProfile = (albumId == Stories::ArchiveId());
|
|
||||||
const auto controller = _controller;
|
const auto controller = _controller;
|
||||||
const auto sure = [=](Fn<void()> close) {
|
const auto sure = [=](Fn<void()> close) {
|
||||||
using namespace ::Media::Stories;
|
using namespace ::Media::Stories;
|
||||||
|
@ -84,6 +84,7 @@ public:
|
|||||||
void unregisterHeavyItem(not_null<const BaseLayout*> item) override;
|
void unregisterHeavyItem(not_null<const BaseLayout*> item) override;
|
||||||
void repaintItem(not_null<const BaseLayout*> item) override;
|
void repaintItem(not_null<const BaseLayout*> item) override;
|
||||||
bool itemVisible(not_null<const BaseLayout*> item) override;
|
bool itemVisible(not_null<const BaseLayout*> item) override;
|
||||||
|
not_null<StickerPremiumMark*> hiddenMark() override;
|
||||||
|
|
||||||
// AbstractTooltipShower interface
|
// AbstractTooltipShower interface
|
||||||
QString tooltipText() const override;
|
QString tooltipText() const override;
|
||||||
@ -192,11 +193,12 @@ private:
|
|||||||
void forwardItems(MessageIdsList &&items);
|
void forwardItems(MessageIdsList &&items);
|
||||||
void deleteSelected();
|
void deleteSelected();
|
||||||
void toggleStoryPinSelected();
|
void toggleStoryPinSelected();
|
||||||
void toggleStoryInProfileSelected();
|
void toggleStoryInProfileSelected(bool toProfile);
|
||||||
void deleteItem(GlobalMsgId globalId);
|
void deleteItem(GlobalMsgId globalId);
|
||||||
void deleteItems(SelectedItems &&items, Fn<void()> confirmed = nullptr);
|
void deleteItems(SelectedItems &&items, Fn<void()> confirmed = nullptr);
|
||||||
void toggleStoryInProfile(
|
void toggleStoryInProfile(
|
||||||
MessageIdsList &&items,
|
MessageIdsList &&items,
|
||||||
|
bool toProfile,
|
||||||
Fn<void()> confirmed = nullptr);
|
Fn<void()> confirmed = nullptr);
|
||||||
void toggleStoryPin(
|
void toggleStoryPin(
|
||||||
MessageIdsList &&items,
|
MessageIdsList &&items,
|
||||||
@ -311,6 +313,7 @@ private:
|
|||||||
int _storiesAddToAlbumId = 0;
|
int _storiesAddToAlbumId = 0;
|
||||||
base::flat_set<StoryId> _storiesInAlbum;
|
base::flat_set<StoryId> _storiesInAlbum;
|
||||||
base::flat_set<MsgId> _storyMsgsToMarkSelected;
|
base::flat_set<MsgId> _storyMsgsToMarkSelected;
|
||||||
|
std::unique_ptr<StickerPremiumMark> _hiddenMark;
|
||||||
|
|
||||||
base::unique_qptr<Ui::PopupMenu> _contextMenu;
|
base::unique_qptr<Ui::PopupMenu> _contextMenu;
|
||||||
rpl::event_stream<> _checkForHide;
|
rpl::event_stream<> _checkForHide;
|
||||||
|
@ -947,10 +947,8 @@ void InnerWidget::refreshAbout() {
|
|||||||
auto text = tr::lng_peer_gifts_empty_search(
|
auto text = tr::lng_peer_gifts_empty_search(
|
||||||
tr::now,
|
tr::now,
|
||||||
Ui::Text::RichLangValue);
|
Ui::Text::RichLangValue);
|
||||||
if (_entries->total > 0) {
|
text.append("\n\n").append(Ui::Text::Link(
|
||||||
text.append("\n\n").append(Ui::Text::Link(
|
tr::lng_peer_gifts_view_all(tr::now)));
|
||||||
tr::lng_peer_gifts_view_all(tr::now)));
|
|
||||||
}
|
|
||||||
auto about = std::make_unique<Ui::FlatLabel>(
|
auto about = std::make_unique<Ui::FlatLabel>(
|
||||||
this,
|
this,
|
||||||
rpl::single(text),
|
rpl::single(text),
|
||||||
|
@ -552,17 +552,18 @@ void InnerWidget::setupEmpty() {
|
|||||||
),
|
),
|
||||||
_list->heightValue()
|
_list->heightValue()
|
||||||
) | rpl::start_with_next([=](auto, int listHeight) {
|
) | rpl::start_with_next([=](auto, int listHeight) {
|
||||||
if (listHeight) {
|
const auto padding = st::infoMediaMargin;
|
||||||
_empty.destroy();
|
if (const auto raw = _empty.release()) {
|
||||||
return;
|
raw->hide();
|
||||||
|
raw->deleteLater();
|
||||||
|
}
|
||||||
|
if (listHeight <= padding.bottom() + padding.top()) {
|
||||||
|
refreshEmpty();
|
||||||
}
|
}
|
||||||
refreshEmpty();
|
|
||||||
}, _list->lifetime());
|
}, _list->lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
void InnerWidget::refreshEmpty() {
|
void InnerWidget::refreshEmpty() {
|
||||||
_empty.destroy();
|
|
||||||
|
|
||||||
const auto albumId = _albumId.current();
|
const auto albumId = _albumId.current();
|
||||||
const auto stories = &_controller->session().data().stories();
|
const auto stories = &_controller->session().data().stories();
|
||||||
const auto knownEmpty = stories->albumIdsCountKnown(_peer->id, albumId);
|
const auto knownEmpty = stories->albumIdsCountKnown(_peer->id, albumId);
|
||||||
@ -606,7 +607,6 @@ void InnerWidget::refreshEmpty() {
|
|||||||
button->setClickedCallback([=] {
|
button->setClickedCallback([=] {
|
||||||
editAlbumStories(albumId);
|
editAlbumStories(albumId);
|
||||||
});
|
});
|
||||||
|
|
||||||
empty->show();
|
empty->show();
|
||||||
_empty = std::move(empty);
|
_empty = std::move(empty);
|
||||||
} else {
|
} else {
|
||||||
@ -790,10 +790,11 @@ void InnerWidget::editAlbumName(int id) {
|
|||||||
|
|
||||||
void InnerWidget::confirmDeleteAlbum(int id) {
|
void InnerWidget::confirmDeleteAlbum(int id) {
|
||||||
const auto done = [=](Fn<void()> close) {
|
const auto done = [=](Fn<void()> close) {
|
||||||
_controller->session().api().request(
|
|
||||||
MTPstories_DeleteAlbum(_peer->input, MTP_int(id))
|
|
||||||
).send();
|
|
||||||
albumRemoved(id);
|
albumRemoved(id);
|
||||||
|
|
||||||
|
const auto stories = &_controller->session().data().stories();
|
||||||
|
stories->albumDelete(_peer, id);
|
||||||
|
|
||||||
close();
|
close();
|
||||||
};
|
};
|
||||||
_controller->uiShow()->show(Ui::MakeConfirmBox({
|
_controller->uiShow()->show(Ui::MakeConfirmBox({
|
||||||
@ -807,7 +808,7 @@ void InnerWidget::confirmDeleteAlbum(int id) {
|
|||||||
void InnerWidget::albumAdded(Data::StoryAlbum result) {
|
void InnerWidget::albumAdded(Data::StoryAlbum result) {
|
||||||
Expects(ranges::contains(_albums, result.id, &Data::StoryAlbum::id));
|
Expects(ranges::contains(_albums, result.id, &Data::StoryAlbum::id));
|
||||||
|
|
||||||
_albumId = result.id;
|
_albumIdChanges.fire_copy(result.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InnerWidget::albumRenamed(int id, QString name) {
|
void InnerWidget::albumRenamed(int id, QString name) {
|
||||||
@ -821,20 +822,8 @@ void InnerWidget::albumRenamed(int id, QString name) {
|
|||||||
void InnerWidget::albumRemoved(int id) {
|
void InnerWidget::albumRemoved(int id) {
|
||||||
auto now = _albumId.current();
|
auto now = _albumId.current();
|
||||||
if (now == id) {
|
if (now == id) {
|
||||||
_albumId = 0;
|
_albumIdChanges.fire_copy(0);
|
||||||
}
|
}
|
||||||
//const auto removeFrom = [&](Entries &entries) {
|
|
||||||
// for (auto &entry : entries.list) {
|
|
||||||
// entry.gift.collectionIds.erase(
|
|
||||||
// ranges::remove(entry.gift.collectionIds, id),
|
|
||||||
// end(entry.gift.collectionIds));
|
|
||||||
// }
|
|
||||||
//};
|
|
||||||
//removeFrom(_all);
|
|
||||||
//for (auto &[_, entries] : _perCollection) {
|
|
||||||
// removeFrom(entries);
|
|
||||||
//}
|
|
||||||
|
|
||||||
const auto i = ranges::find(_albums, id, &Data::StoryAlbum::id);
|
const auto i = ranges::find(_albums, id, &Data::StoryAlbum::id);
|
||||||
if (i != end(_albums)) {
|
if (i != end(_albums)) {
|
||||||
_albums.erase(i);
|
_albums.erase(i);
|
||||||
@ -908,14 +897,6 @@ int InnerWidget::recountHeight() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void InnerWidget::setScrollHeightValue(rpl::producer<int> value) {
|
void InnerWidget::setScrollHeightValue(rpl::producer<int> value) {
|
||||||
//using namespace rpl::mappers;
|
|
||||||
//_empty->setFullHeight(rpl::combine(
|
|
||||||
// std::move(value),
|
|
||||||
// _listTops.events_starting_with(
|
|
||||||
// _list->topValue()
|
|
||||||
// ) | rpl::flatten_latest(),
|
|
||||||
// _topHeight.value(),
|
|
||||||
// _1 - _2 + _3));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<Ui::ScrollToRequest> InnerWidget::scrollToRequests() const {
|
rpl::producer<Ui::ScrollToRequest> InnerWidget::scrollToRequests() const {
|
||||||
|
@ -343,10 +343,20 @@ std::unique_ptr<BaseLayout> Provider::createLayout(
|
|||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const auto peer = item->history()->peer;
|
||||||
|
const auto channel = peer->asChannel();
|
||||||
|
const auto showPinned = (_albumId == Data::kStoriesAlbumIdSaved);
|
||||||
|
const auto showHidden = peer->isSelf()
|
||||||
|
|| (channel && channel->canEditStories());
|
||||||
|
|
||||||
using namespace Overview::Layout;
|
using namespace Overview::Layout;
|
||||||
const auto options = MediaOptions{
|
const auto options = MediaOptions{
|
||||||
.pinned = item->isPinned(),
|
|
||||||
.story = true,
|
.story = true,
|
||||||
|
.storyPinned = showPinned && item->isPinned(),
|
||||||
|
.storyShowPinned = showPinned,
|
||||||
|
.storyHidden = showHidden && !item->storyInProfile(),
|
||||||
|
.storyShowHidden = showHidden,
|
||||||
};
|
};
|
||||||
if (const auto photo = getPhoto()) {
|
if (const auto photo = getPhoto()) {
|
||||||
return std::make_unique<Photo>(delegate, item, photo, options);
|
return std::make_unique<Photo>(delegate, item, photo, options);
|
||||||
@ -379,6 +389,7 @@ ListItemSelectionData Provider::computeSelectionData(
|
|||||||
result.canForward = peer->isSelf() && story->canShare();
|
result.canForward = peer->isSelf() && story->canShare();
|
||||||
result.canDelete = story->canDelete();
|
result.canDelete = story->canDelete();
|
||||||
result.canUnpinStory = story->pinnedToTop();
|
result.canUnpinStory = story->pinnedToTop();
|
||||||
|
result.storyInProfile = story->inProfile();
|
||||||
}
|
}
|
||||||
result.canToggleStoryPin = peer->isSelf()
|
result.canToggleStoryPin = peer->isSelf()
|
||||||
|| (channel && channel->canEditStories());
|
|| (channel && channel->canEditStories());
|
||||||
|
@ -248,7 +248,7 @@ inputReportReasonFake#f5ddd6e7 = ReportReason;
|
|||||||
inputReportReasonIllegalDrugs#a8eb2be = ReportReason;
|
inputReportReasonIllegalDrugs#a8eb2be = ReportReason;
|
||||||
inputReportReasonPersonalDetails#9ec7863d = ReportReason;
|
inputReportReasonPersonalDetails#9ec7863d = ReportReason;
|
||||||
|
|
||||||
userFull#29de80be flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true voice_messages_forbidden:flags.20?true translations_disabled:flags.23?true stories_pinned_available:flags.26?true blocked_my_stories_from:flags.27?true wallpaper_overridden:flags.28?true contact_require_premium:flags.29?true read_dates_private:flags.30?true flags2:# sponsored_enabled:flags2.7?true can_view_revenue:flags2.9?true bot_can_manage_emoji_status:flags2.10?true display_gifts_button:flags2.16?true id:long about:flags.1?string settings:PeerSettings personal_photo:flags.21?Photo profile_photo:flags.2?Photo fallback_photo:flags.22?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int ttl_period:flags.14?int theme_emoticon:flags.15?string private_forward_name:flags.16?string bot_group_admin_rights:flags.17?ChatAdminRights bot_broadcast_admin_rights:flags.18?ChatAdminRights wallpaper:flags.24?WallPaper stories:flags.25?PeerStories business_work_hours:flags2.0?BusinessWorkHours business_location:flags2.1?BusinessLocation business_greeting_message:flags2.2?BusinessGreetingMessage business_away_message:flags2.3?BusinessAwayMessage business_intro:flags2.4?BusinessIntro birthday:flags2.5?Birthday personal_channel_id:flags2.6?long personal_channel_message:flags2.6?int stargifts_count:flags2.8?int starref_program:flags2.11?StarRefProgram bot_verification:flags2.12?BotVerification send_paid_messages_stars:flags2.14?long disallowed_gifts:flags2.15?DisallowedGiftsSettings stars_rating:flags2.17?StarsRating = UserFull;
|
userFull#7e63ce1f flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true voice_messages_forbidden:flags.20?true translations_disabled:flags.23?true stories_pinned_available:flags.26?true blocked_my_stories_from:flags.27?true wallpaper_overridden:flags.28?true contact_require_premium:flags.29?true read_dates_private:flags.30?true flags2:# sponsored_enabled:flags2.7?true can_view_revenue:flags2.9?true bot_can_manage_emoji_status:flags2.10?true display_gifts_button:flags2.16?true id:long about:flags.1?string settings:PeerSettings personal_photo:flags.21?Photo profile_photo:flags.2?Photo fallback_photo:flags.22?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int ttl_period:flags.14?int theme_emoticon:flags.15?string private_forward_name:flags.16?string bot_group_admin_rights:flags.17?ChatAdminRights bot_broadcast_admin_rights:flags.18?ChatAdminRights wallpaper:flags.24?WallPaper stories:flags.25?PeerStories business_work_hours:flags2.0?BusinessWorkHours business_location:flags2.1?BusinessLocation business_greeting_message:flags2.2?BusinessGreetingMessage business_away_message:flags2.3?BusinessAwayMessage business_intro:flags2.4?BusinessIntro birthday:flags2.5?Birthday personal_channel_id:flags2.6?long personal_channel_message:flags2.6?int stargifts_count:flags2.8?int starref_program:flags2.11?StarRefProgram bot_verification:flags2.12?BotVerification send_paid_messages_stars:flags2.14?long disallowed_gifts:flags2.15?DisallowedGiftsSettings stars_rating:flags2.17?StarsRating stars_my_pending_rating:flags2.18?StarsRating stars_my_pending_rating_date:flags2.18?int = UserFull;
|
||||||
|
|
||||||
contact#145ade0b user_id:long mutual:Bool = Contact;
|
contact#145ade0b user_id:long mutual:Bool = Contact;
|
||||||
|
|
||||||
@ -2001,7 +2001,7 @@ storyAlbum#9325705a flags:# album_id:int title:string icon_photo:flags.0?Photo i
|
|||||||
stories.albumsNotModified#564edaeb = stories.Albums;
|
stories.albumsNotModified#564edaeb = stories.Albums;
|
||||||
stories.albums#c3987a3a hash:long albums:Vector<StoryAlbum> = stories.Albums;
|
stories.albums#c3987a3a hash:long albums:Vector<StoryAlbum> = stories.Albums;
|
||||||
|
|
||||||
searchPostsFlood#940e707c flags:# remains:int wait_till:flags.0?int stars_amount:long = SearchPostsFlood;
|
searchPostsFlood#3e0b5b6a flags:# query_is_free:flags.0?true total_daily:int remains:int wait_till:flags.1?int stars_amount:long = SearchPostsFlood;
|
||||||
|
|
||||||
---functions---
|
---functions---
|
||||||
|
|
||||||
@ -2530,7 +2530,7 @@ channels.searchPosts#f2c4f24d flags:# hashtag:flags.0?string query:flags.1?strin
|
|||||||
channels.updatePaidMessagesPrice#4b12327b flags:# broadcast_messages_allowed:flags.0?true channel:InputChannel send_paid_messages_stars:long = Updates;
|
channels.updatePaidMessagesPrice#4b12327b flags:# broadcast_messages_allowed:flags.0?true channel:InputChannel send_paid_messages_stars:long = Updates;
|
||||||
channels.toggleAutotranslation#167fc0a1 channel:InputChannel enabled:Bool = Updates;
|
channels.toggleAutotranslation#167fc0a1 channel:InputChannel enabled:Bool = Updates;
|
||||||
channels.getMessageAuthor#ece2a0e6 channel:InputChannel id:int = User;
|
channels.getMessageAuthor#ece2a0e6 channel:InputChannel id:int = User;
|
||||||
channels.checkSearchPostsFlood#bba9f121 = SearchPostsFlood;
|
channels.checkSearchPostsFlood#22567115 flags:# query:flags.0?string = SearchPostsFlood;
|
||||||
|
|
||||||
bots.sendCustomRequest#aa2769ed custom_method:string params:DataJSON = DataJSON;
|
bots.sendCustomRequest#aa2769ed custom_method:string params:DataJSON = DataJSON;
|
||||||
bots.answerWebhookJSONQuery#e6213f4d query_id:long data:DataJSON = Bool;
|
bots.answerWebhookJSONQuery#e6213f4d query_id:long data:DataJSON = Bool;
|
||||||
|
@ -33,6 +33,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
#include "history/view/media/history_view_media_common.h"
|
#include "history/view/media/history_view_media_common.h"
|
||||||
#include "history/view/media/history_view_document.h" // DrawThumbnailAsSongCover
|
#include "history/view/media/history_view_document.h" // DrawThumbnailAsSongCover
|
||||||
#include "base/unixtime.h"
|
#include "base/unixtime.h"
|
||||||
|
#include "boxes/sticker_set_box.h"
|
||||||
#include "ui/effects/round_checkbox.h"
|
#include "ui/effects/round_checkbox.h"
|
||||||
#include "ui/effects/spoiler_mess.h"
|
#include "ui/effects/spoiler_mess.h"
|
||||||
#include "ui/image/image.h"
|
#include "ui/image/image.h"
|
||||||
@ -355,8 +356,11 @@ Photo::Photo(
|
|||||||
})
|
})
|
||||||
: nullptr)
|
: nullptr)
|
||||||
, _sensitiveSpoiler(parent->isMediaSensitive() ? 1 : 0)
|
, _sensitiveSpoiler(parent->isMediaSensitive() ? 1 : 0)
|
||||||
, _pinned(options.pinned)
|
|
||||||
, _story(options.story)
|
, _story(options.story)
|
||||||
|
, _storyPinned(options.storyPinned)
|
||||||
|
, _storyShowPinned(options.storyShowPinned)
|
||||||
|
, _storyHidden(options.storyHidden)
|
||||||
|
, _storyShowHidden(options.storyShowHidden)
|
||||||
, _link(_sensitiveSpoiler
|
, _link(_sensitiveSpoiler
|
||||||
? HistoryView::MakeSensitiveMediaLink(
|
? HistoryView::MakeSensitiveMediaLink(
|
||||||
std::make_shared<LambdaClickHandler>(crl::guard(this, [=] {
|
std::make_shared<LambdaClickHandler>(crl::guard(this, [=] {
|
||||||
@ -408,7 +412,7 @@ void Photo::paint(Painter &p, const QRect &clip, TextSelection selection, const
|
|||||||
|| _dataMedia->image(Data::PhotoSize::Thumbnail));
|
|| _dataMedia->image(Data::PhotoSize::Thumbnail));
|
||||||
if ((good && !_goodLoaded) || widthChanged) {
|
if ((good && !_goodLoaded) || widthChanged) {
|
||||||
_goodLoaded = good;
|
_goodLoaded = good;
|
||||||
_pix = QPixmap();
|
_pix = QImage();
|
||||||
if (_goodLoaded) {
|
if (_goodLoaded) {
|
||||||
setPixFrom(_dataMedia->image(Data::PhotoSize::Large)
|
setPixFrom(_dataMedia->image(Data::PhotoSize::Large)
|
||||||
? _dataMedia->image(Data::PhotoSize::Large)
|
? _dataMedia->image(Data::PhotoSize::Large)
|
||||||
@ -426,7 +430,7 @@ void Photo::paint(Painter &p, const QRect &clip, TextSelection selection, const
|
|||||||
if (_pix.isNull()) {
|
if (_pix.isNull()) {
|
||||||
p.fillRect(0, 0, _width, _height, st::overviewPhotoBg);
|
p.fillRect(0, 0, _width, _height, st::overviewPhotoBg);
|
||||||
} else {
|
} else {
|
||||||
p.drawPixmap(0, 0, _pix);
|
p.drawImage(0, 0, _pix);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_spoiler) {
|
if (_spoiler) {
|
||||||
@ -442,11 +446,21 @@ void Photo::paint(Painter &p, const QRect &clip, TextSelection selection, const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_storyHidden) {
|
||||||
|
delegate()->hiddenMark()->paint(
|
||||||
|
p,
|
||||||
|
_pix,
|
||||||
|
_hiddenBgCache,
|
||||||
|
QPoint(),
|
||||||
|
QSize(_width, _height),
|
||||||
|
_width);
|
||||||
|
}
|
||||||
|
|
||||||
if (selected) {
|
if (selected) {
|
||||||
p.fillRect(0, 0, _width, _height, st::overviewPhotoSelectOverlay);
|
p.fillRect(0, 0, _width, _height, st::overviewPhotoSelectOverlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_pinned) {
|
if (_storyPinned) {
|
||||||
const auto &icon = selected
|
const auto &icon = selected
|
||||||
? st::storyPinnedIconSelected
|
? st::storyPinnedIconSelected
|
||||||
: st::storyPinnedIcon;
|
: st::storyPinnedIcon;
|
||||||
@ -466,8 +480,7 @@ void Photo::setPixFrom(not_null<Image*> image) {
|
|||||||
if (!_goodLoaded) {
|
if (!_goodLoaded) {
|
||||||
img = Images::Blur(std::move(img));
|
img = Images::Blur(std::move(img));
|
||||||
}
|
}
|
||||||
_pix = Ui::PixmapFromImage(
|
_pix = CropMediaFrame(std::move(img), _width, _height);
|
||||||
CropMediaFrame(std::move(img), _width, _height));
|
|
||||||
|
|
||||||
// In case we have inline thumbnail we can unload all images and we still
|
// In case we have inline thumbnail we can unload all images and we still
|
||||||
// won't get a blank image in the media viewer when the photo is opened.
|
// won't get a blank image in the media viewer when the photo is opened.
|
||||||
@ -493,7 +506,7 @@ void Photo::clearSpoiler() {
|
|||||||
if (_spoiler) {
|
if (_spoiler) {
|
||||||
_spoiler = nullptr;
|
_spoiler = nullptr;
|
||||||
_sensitiveSpoiler = false;
|
_sensitiveSpoiler = false;
|
||||||
_pix = QPixmap();
|
_pix = QImage();
|
||||||
delegate()->repaintItem(this);
|
delegate()->repaintItem(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -506,9 +519,11 @@ void Photo::maybeClearSensitiveSpoiler() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Photo::itemDataChanged() {
|
void Photo::itemDataChanged() {
|
||||||
const auto pinned = parent()->isPinned();
|
const auto pinned = _storyShowPinned && parent()->isPinned();
|
||||||
if (_pinned != pinned) {
|
const auto hidden = _storyShowHidden && !parent()->storyInProfile();
|
||||||
_pinned = pinned;
|
if (_storyPinned != pinned || _storyHidden != hidden) {
|
||||||
|
_storyPinned = pinned;
|
||||||
|
_storyHidden = hidden;
|
||||||
delegate()->repaintItem(this);
|
delegate()->repaintItem(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -541,8 +556,11 @@ Video::Video(
|
|||||||
})
|
})
|
||||||
: nullptr)
|
: nullptr)
|
||||||
, _sensitiveSpoiler(parent->isMediaSensitive() ? 1 : 0)
|
, _sensitiveSpoiler(parent->isMediaSensitive() ? 1 : 0)
|
||||||
, _pinned(options.pinned)
|
, _story(options.story)
|
||||||
, _story(options.story) {
|
, _storyPinned(options.storyPinned)
|
||||||
|
, _storyShowPinned(options.storyShowPinned)
|
||||||
|
, _storyHidden(options.storyHidden)
|
||||||
|
, _storyShowHidden(options.storyShowHidden) {
|
||||||
setDocumentLinks(_data);
|
setDocumentLinks(_data);
|
||||||
if (_sensitiveSpoiler) {
|
if (_sensitiveSpoiler) {
|
||||||
_openl = HistoryView::MakeSensitiveMediaLink(
|
_openl = HistoryView::MakeSensitiveMediaLink(
|
||||||
@ -577,7 +595,11 @@ int32 Video::resizeGetHeight(int32 width) {
|
|||||||
return _height;
|
return _height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Video::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) {
|
void Video::paint(
|
||||||
|
Painter &p,
|
||||||
|
const QRect &clip,
|
||||||
|
TextSelection selection,
|
||||||
|
const PaintContext *context) {
|
||||||
ensureDataMediaCreated();
|
ensureDataMediaCreated();
|
||||||
|
|
||||||
const auto selected = (selection == FullSelection);
|
const auto selected = (selection == FullSelection);
|
||||||
@ -614,15 +636,14 @@ void Video::paint(Painter &p, const QRect &clip, TextSelection selection, const
|
|||||||
: thumbnail
|
: thumbnail
|
||||||
? thumbnail->original()
|
? thumbnail->original()
|
||||||
: Images::Blur(blurred->original());
|
: Images::Blur(blurred->original());
|
||||||
_pix = Ui::PixmapFromImage(
|
_pix = CropMediaFrame(std::move(img), _width, _height);
|
||||||
CropMediaFrame(std::move(img), _width, _height));
|
|
||||||
_pixBlurred = !(thumbnail || good);
|
_pixBlurred = !(thumbnail || good);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_pix.isNull()) {
|
if (_pix.isNull()) {
|
||||||
p.fillRect(0, 0, _width, _height, st::overviewPhotoBg);
|
p.fillRect(0, 0, _width, _height, st::overviewPhotoBg);
|
||||||
} else {
|
} else {
|
||||||
p.drawPixmap(0, 0, _pix);
|
p.drawImage(0, 0, _pix);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_spoiler) {
|
if (_spoiler) {
|
||||||
@ -638,11 +659,21 @@ void Video::paint(Painter &p, const QRect &clip, TextSelection selection, const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_storyHidden) {
|
||||||
|
delegate()->hiddenMark()->paint(
|
||||||
|
p,
|
||||||
|
_pix,
|
||||||
|
_hiddenBgCache,
|
||||||
|
QPoint(),
|
||||||
|
QSize(_width, _height),
|
||||||
|
_width);
|
||||||
|
}
|
||||||
|
|
||||||
if (selected) {
|
if (selected) {
|
||||||
p.fillRect(QRect(0, 0, _width, _height), st::overviewPhotoSelectOverlay);
|
p.fillRect(QRect(0, 0, _width, _height), st::overviewPhotoSelectOverlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_pinned) {
|
if (_storyPinned) {
|
||||||
const auto &icon = selected
|
const auto &icon = selected
|
||||||
? st::storyPinnedIconSelected
|
? st::storyPinnedIconSelected
|
||||||
: st::storyPinnedIcon;
|
: st::storyPinnedIcon;
|
||||||
@ -723,7 +754,7 @@ void Video::clearSpoiler() {
|
|||||||
if (_spoiler) {
|
if (_spoiler) {
|
||||||
_spoiler = nullptr;
|
_spoiler = nullptr;
|
||||||
_sensitiveSpoiler = false;
|
_sensitiveSpoiler = false;
|
||||||
_pix = QPixmap();
|
_pix = QImage();
|
||||||
delegate()->repaintItem(this);
|
delegate()->repaintItem(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -736,9 +767,11 @@ void Video::maybeClearSensitiveSpoiler() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Video::itemDataChanged() {
|
void Video::itemDataChanged() {
|
||||||
const auto pinned = parent()->isPinned();
|
const auto pinned = _storyShowPinned && parent()->isPinned();
|
||||||
if (_pinned != pinned) {
|
const auto hidden = _storyShowHidden && !parent()->storyInProfile();
|
||||||
_pinned = pinned;
|
if (_storyPinned != pinned || _storyHidden != hidden) {
|
||||||
|
_storyPinned = pinned;
|
||||||
|
_storyHidden = hidden;
|
||||||
delegate()->repaintItem(this);
|
delegate()->repaintItem(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -190,8 +190,11 @@ struct Info : RuntimeComponent<Info, LayoutItemBase> {
|
|||||||
|
|
||||||
struct MediaOptions {
|
struct MediaOptions {
|
||||||
bool spoiler = false;
|
bool spoiler = false;
|
||||||
bool pinned = false;
|
|
||||||
bool story = false;
|
bool story = false;
|
||||||
|
bool storyPinned = false;
|
||||||
|
bool storyShowPinned = false;
|
||||||
|
bool storyHidden = false;
|
||||||
|
bool storyShowHidden = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Photo final : public ItemBase {
|
class Photo final : public ItemBase {
|
||||||
@ -225,11 +228,15 @@ private:
|
|||||||
mutable std::shared_ptr<Data::PhotoMedia> _dataMedia;
|
mutable std::shared_ptr<Data::PhotoMedia> _dataMedia;
|
||||||
std::unique_ptr<Ui::SpoilerAnimation> _spoiler;
|
std::unique_ptr<Ui::SpoilerAnimation> _spoiler;
|
||||||
|
|
||||||
QPixmap _pix;
|
QImage _pix;
|
||||||
bool _goodLoaded = false;
|
QImage _hiddenBgCache;
|
||||||
bool _sensitiveSpoiler = false;
|
bool _goodLoaded : 1 = false;
|
||||||
bool _pinned = false;
|
bool _sensitiveSpoiler : 1 = false;
|
||||||
bool _story = false;
|
bool _story : 1 = false;
|
||||||
|
bool _storyPinned : 1 = false;
|
||||||
|
bool _storyShowPinned : 1 = false;
|
||||||
|
bool _storyHidden : 1 = false;
|
||||||
|
bool _storyShowHidden : 1 = false;
|
||||||
|
|
||||||
ClickHandlerPtr _link;
|
ClickHandlerPtr _link;
|
||||||
|
|
||||||
@ -339,11 +346,15 @@ private:
|
|||||||
QString _duration;
|
QString _duration;
|
||||||
std::unique_ptr<Ui::SpoilerAnimation> _spoiler;
|
std::unique_ptr<Ui::SpoilerAnimation> _spoiler;
|
||||||
|
|
||||||
QPixmap _pix;
|
QImage _pix;
|
||||||
bool _pixBlurred = true;
|
QImage _hiddenBgCache;
|
||||||
bool _sensitiveSpoiler = false;
|
bool _pixBlurred : 1 = true;
|
||||||
bool _pinned = false;
|
bool _sensitiveSpoiler : 1 = false;
|
||||||
bool _story = false;
|
bool _story : 1 = false;
|
||||||
|
bool _storyPinned : 1 = false;
|
||||||
|
bool _storyShowPinned : 1 = false;
|
||||||
|
bool _storyHidden : 1 = false;
|
||||||
|
bool _storyShowHidden : 1 = false;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
class StickerPremiumMark;
|
||||||
|
|
||||||
namespace Overview {
|
namespace Overview {
|
||||||
namespace Layout {
|
namespace Layout {
|
||||||
|
|
||||||
@ -19,6 +21,8 @@ public:
|
|||||||
virtual void repaintItem(not_null<const ItemBase*> item) = 0;
|
virtual void repaintItem(not_null<const ItemBase*> item) = 0;
|
||||||
virtual bool itemVisible(not_null<const ItemBase*> item) = 0;
|
virtual bool itemVisible(not_null<const ItemBase*> item) = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual not_null<StickerPremiumMark*> hiddenMark() = 0;
|
||||||
|
|
||||||
virtual void openPhoto(not_null<PhotoData*> photo, FullMsgId id) = 0;
|
virtual void openPhoto(not_null<PhotoData*> photo, FullMsgId id) = 0;
|
||||||
virtual void openDocument(
|
virtual void openDocument(
|
||||||
not_null<DocumentData*> document,
|
not_null<DocumentData*> document,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user