mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Save to Profile / Archive / Delete in list.
This commit is contained in:
parent
af0e578da5
commit
5f72a5238c
14 changed files with 179 additions and 36 deletions
|
@ -1298,6 +1298,8 @@ void Stories::togglePinnedList(
|
||||||
const auto loaded = saved.loaded;
|
const auto loaded = saved.loaded;
|
||||||
const auto lastId = !saved.ids.list.empty()
|
const auto lastId = !saved.ids.list.empty()
|
||||||
? saved.ids.list.back()
|
? saved.ids.list.back()
|
||||||
|
: saved.lastId
|
||||||
|
? saved.lastId
|
||||||
: std::numeric_limits<StoryId>::max();
|
: std::numeric_limits<StoryId>::max();
|
||||||
auto dirty = false;
|
auto dirty = false;
|
||||||
for (const auto &id : result.v) {
|
for (const auto &id : result.v) {
|
||||||
|
|
|
@ -44,7 +44,7 @@ rpl::producer<StoriesIdsSlice> SavedStoriesIds(
|
||||||
const auto hasBefore = int(around - begin(saved->list));
|
const auto hasBefore = int(around - begin(saved->list));
|
||||||
const auto hasAfter = int(end(saved->list) - around);
|
const auto hasAfter = int(end(saved->list) - around);
|
||||||
if (hasAfter < limit) {
|
if (hasAfter < limit) {
|
||||||
//stories->savedLoadMore(peer->id);
|
stories->savedLoadMore(peer->id);
|
||||||
}
|
}
|
||||||
const auto takeBefore = std::min(hasBefore, limit);
|
const auto takeBefore = std::min(hasBefore, limit);
|
||||||
const auto takeAfter = std::min(hasAfter, limit);
|
const auto takeAfter = std::min(hasAfter, limit);
|
||||||
|
|
|
@ -1988,7 +1988,7 @@ bool HistoryItem::canDelete() const {
|
||||||
if (isSponsored()) {
|
if (isSponsored()) {
|
||||||
return false;
|
return false;
|
||||||
} else if (IsStoryMsgId(id)) {
|
} else if (IsStoryMsgId(id)) {
|
||||||
return false && _history->peer->isSelf(); // #TODO stories
|
return false;
|
||||||
} else if (isService() && !isRegular()) {
|
} else if (isService() && !isRegular()) {
|
||||||
return false;
|
return false;
|
||||||
} else if (topicRootId() == id) {
|
} else if (topicRootId() == id) {
|
||||||
|
|
|
@ -352,6 +352,10 @@ void TopBar::updateSelectionControlsGeometry(int newWidth) {
|
||||||
_delete->moveToRight(right, 0, newWidth);
|
_delete->moveToRight(right, 0, newWidth);
|
||||||
right += _delete->width();
|
right += _delete->width();
|
||||||
}
|
}
|
||||||
|
if (_canToggleStoryPin) {
|
||||||
|
_toggleStoryPin->moveToRight(right, 0, newWidth);
|
||||||
|
right += _toggleStoryPin->width();
|
||||||
|
}
|
||||||
if (_canForward) {
|
if (_canForward) {
|
||||||
_forward->moveToRight(right, 0, newWidth);
|
_forward->moveToRight(right, 0, newWidth);
|
||||||
right += _forward->width();
|
right += _forward->width();
|
||||||
|
@ -496,6 +500,10 @@ 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);
|
||||||
|
@ -523,13 +531,14 @@ rpl::producer<SelectionAction> TopBar::selectionActionRequests() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TopBar::updateSelectionState() {
|
void TopBar::updateSelectionState() {
|
||||||
Expects(_selectionText && _delete && _forward);
|
Expects(_selectionText && _delete && _forward && _toggleStoryPin);
|
||||||
|
|
||||||
_canDelete = computeCanDelete();
|
_canDelete = computeCanDelete();
|
||||||
_canForward = computeCanForward();
|
_canForward = computeCanForward();
|
||||||
_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);
|
||||||
|
_toggleStoryPin->toggle(_canToggleStoryPin, anim::type::instant);
|
||||||
|
|
||||||
updateSelectionControlsGeometry(width());
|
updateSelectionControlsGeometry(width());
|
||||||
}
|
}
|
||||||
|
@ -544,6 +553,7 @@ void TopBar::createSelectionControls() {
|
||||||
};
|
};
|
||||||
_canDelete = computeCanDelete();
|
_canDelete = computeCanDelete();
|
||||||
_canForward = computeCanForward();
|
_canForward = computeCanForward();
|
||||||
|
_canToggleStoryPin = computeCanToggleStoryPin();
|
||||||
_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),
|
||||||
|
@ -595,6 +605,24 @@ void TopBar::createSelectionControls() {
|
||||||
_selectionActionRequests,
|
_selectionActionRequests,
|
||||||
_cancelSelection->lifetime());
|
_cancelSelection->lifetime());
|
||||||
_delete->entity()->setVisible(_canDelete);
|
_delete->entity()->setVisible(_canDelete);
|
||||||
|
const auto archive =
|
||||||
|
_toggleStoryPin = wrap(Ui::CreateChild<Ui::FadeWrap<Ui::IconButton>>(
|
||||||
|
this,
|
||||||
|
object_ptr<Ui::IconButton>(
|
||||||
|
this,
|
||||||
|
_storiesArchive ? _st.storiesSave : _st.storiesArchive),
|
||||||
|
st::infoTopBarScale));
|
||||||
|
registerToggleControlCallback(
|
||||||
|
_toggleStoryPin.data(),
|
||||||
|
[this] { return selectionMode() && _canToggleStoryPin; });
|
||||||
|
_toggleStoryPin->setDuration(st::infoTopBarDuration);
|
||||||
|
_toggleStoryPin->entity()->clicks(
|
||||||
|
) | rpl::map_to(
|
||||||
|
SelectionAction::ToggleStoryPin
|
||||||
|
) | rpl::start_to_stream(
|
||||||
|
_selectionActionRequests,
|
||||||
|
_cancelSelection->lifetime());
|
||||||
|
_toggleStoryPin->entity()->setVisible(_canToggleStoryPin);
|
||||||
|
|
||||||
updateControlsGeometry(width());
|
updateControlsGeometry(width());
|
||||||
}
|
}
|
||||||
|
@ -607,6 +635,12 @@ bool TopBar::computeCanForward() const {
|
||||||
return ranges::all_of(_selectedItems.list, &SelectedItem::canForward);
|
return ranges::all_of(_selectedItems.list, &SelectedItem::canForward);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TopBar::computeCanToggleStoryPin() const {
|
||||||
|
return ranges::all_of(
|
||||||
|
_selectedItems.list,
|
||||||
|
&SelectedItem::canToggleStoryPin);
|
||||||
|
}
|
||||||
|
|
||||||
Ui::StringWithNumbers TopBar::generateSelectedText() const {
|
Ui::StringWithNumbers TopBar::generateSelectedText() const {
|
||||||
using Type = Storage::SharedMediaType;
|
using Type = Storage::SharedMediaType;
|
||||||
const auto phrase = [&] {
|
const auto phrase = [&] {
|
||||||
|
@ -618,8 +652,7 @@ Ui::StringWithNumbers TopBar::generateSelectedText() const {
|
||||||
case Type::MusicFile: return tr::lng_media_selected_song;
|
case Type::MusicFile: return tr::lng_media_selected_song;
|
||||||
case Type::Link: return tr::lng_media_selected_link;
|
case Type::Link: return tr::lng_media_selected_link;
|
||||||
case Type::RoundVoiceFile: return tr::lng_media_selected_audio;
|
case Type::RoundVoiceFile: return tr::lng_media_selected_audio;
|
||||||
// #TODO stories
|
case Type::PhotoVideo: return tr::lng_stories_row_count;
|
||||||
case Type::PhotoVideo: return tr::lng_media_selected_photo;
|
|
||||||
}
|
}
|
||||||
Unexpected("Type in TopBar::generateSelectedText()");
|
Unexpected("Type in TopBar::generateSelectedText()");
|
||||||
}();
|
}();
|
||||||
|
|
|
@ -57,6 +57,7 @@ public:
|
||||||
|
|
||||||
void setTitle(rpl::producer<QString> &&title);
|
void setTitle(rpl::producer<QString> &&title);
|
||||||
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();
|
||||||
|
|
||||||
|
@ -120,11 +121,13 @@ private:
|
||||||
[[nodiscard]] Ui::StringWithNumbers generateSelectedText() const;
|
[[nodiscard]] Ui::StringWithNumbers generateSelectedText() const;
|
||||||
[[nodiscard]] bool computeCanDelete() const;
|
[[nodiscard]] bool computeCanDelete() const;
|
||||||
[[nodiscard]] bool computeCanForward() const;
|
[[nodiscard]] bool computeCanForward() const;
|
||||||
|
[[nodiscard]] bool computeCanToggleStoryPin() const;
|
||||||
void updateSelectionState();
|
void updateSelectionState();
|
||||||
void createSelectionControls();
|
void createSelectionControls();
|
||||||
|
|
||||||
void performForward();
|
void performForward();
|
||||||
void performDelete();
|
void performDelete();
|
||||||
|
void performToggleStoryPin();
|
||||||
|
|
||||||
void setSearchField(
|
void setSearchField(
|
||||||
base::unique_qptr<Ui::InputField> field,
|
base::unique_qptr<Ui::InputField> field,
|
||||||
|
@ -163,10 +166,13 @@ private:
|
||||||
SelectedItems _selectedItems;
|
SelectedItems _selectedItems;
|
||||||
bool _canDelete = false;
|
bool _canDelete = false;
|
||||||
bool _canForward = false;
|
bool _canForward = false;
|
||||||
|
bool _canToggleStoryPin = false;
|
||||||
|
bool _storiesArchive = 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;
|
||||||
QPointer<Ui::FadeWrap<Ui::IconButton>> _delete;
|
QPointer<Ui::FadeWrap<Ui::IconButton>> _delete;
|
||||||
|
QPointer<Ui::FadeWrap<Ui::IconButton>> _toggleStoryPin;
|
||||||
rpl::event_stream<SelectionAction> _selectionActionRequests;
|
rpl::event_stream<SelectionAction> _selectionActionRequests;
|
||||||
|
|
||||||
QPointer<Ui::FadeWrap<Dialogs::Stories::List>> _stories;
|
QPointer<Ui::FadeWrap<Dialogs::Stories::List>> _stories;
|
||||||
|
|
|
@ -585,6 +585,8 @@ void WrapWidget::finishShowContent() {
|
||||||
if (_topBar) {
|
if (_topBar) {
|
||||||
_topBar->setTitle(_content->title());
|
_topBar->setTitle(_content->title());
|
||||||
_topBar->setStories(_content->titleStories());
|
_topBar->setStories(_content->titleStories());
|
||||||
|
_topBar->setStoriesArchive(
|
||||||
|
_controller->key().storiesTab() == Stories::Tab::Archive);
|
||||||
}
|
}
|
||||||
_desiredHeights.fire(desiredHeightForContent());
|
_desiredHeights.fire(desiredHeightForContent());
|
||||||
_desiredShadowVisibilities.fire(_content->desiredShadowVisibility());
|
_desiredShadowVisibilities.fire(_content->desiredShadowVisibility());
|
||||||
|
|
|
@ -58,6 +58,7 @@ struct SelectedItem {
|
||||||
GlobalMsgId globalId;
|
GlobalMsgId globalId;
|
||||||
bool canDelete = false;
|
bool canDelete = false;
|
||||||
bool canForward = false;
|
bool canForward = false;
|
||||||
|
bool canToggleStoryPin = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SelectedItems {
|
struct SelectedItems {
|
||||||
|
@ -73,6 +74,7 @@ enum class SelectionAction {
|
||||||
Clear,
|
Clear,
|
||||||
Forward,
|
Forward,
|
||||||
Delete,
|
Delete,
|
||||||
|
ToggleStoryPin,
|
||||||
};
|
};
|
||||||
|
|
||||||
class WrapWidget final : public Window::SectionWidget {
|
class WrapWidget final : public Window::SectionWidget {
|
||||||
|
|
|
@ -30,15 +30,12 @@ struct ListItemSelectionData {
|
||||||
TextSelection text;
|
TextSelection text;
|
||||||
bool canDelete = false;
|
bool canDelete = false;
|
||||||
bool canForward = false;
|
bool canForward = false;
|
||||||
};
|
bool canToggleStoryPin = false;
|
||||||
|
|
||||||
inline bool operator==(
|
friend inline bool operator==(
|
||||||
ListItemSelectionData a,
|
ListItemSelectionData,
|
||||||
ListItemSelectionData b) {
|
ListItemSelectionData) = default;
|
||||||
return (a.text == b.text)
|
};
|
||||||
&& (a.canDelete == b.canDelete)
|
|
||||||
&& (a.canForward == b.canForward);
|
|
||||||
}
|
|
||||||
|
|
||||||
using ListSelectedMap = base::flat_map<
|
using ListSelectedMap = base::flat_map<
|
||||||
not_null<const HistoryItem*>,
|
not_null<const HistoryItem*>,
|
||||||
|
|
|
@ -338,7 +338,7 @@ void ListSection::resizeToWidth(int newWidth) {
|
||||||
switch (_type) {
|
switch (_type) {
|
||||||
case Type::Photo:
|
case Type::Photo:
|
||||||
case Type::Video:
|
case Type::Video:
|
||||||
case Type::PhotoVideo: // #TODO stories
|
case Type::PhotoVideo:
|
||||||
case Type::RoundFile: {
|
case Type::RoundFile: {
|
||||||
const auto skip = st::infoMediaSkip;
|
const auto skip = st::infoMediaSkip;
|
||||||
_itemsLeft = st::infoMediaLeft;
|
_itemsLeft = st::infoMediaLeft;
|
||||||
|
@ -379,7 +379,7 @@ int ListSection::recountHeight() {
|
||||||
switch (_type) {
|
switch (_type) {
|
||||||
case Type::Photo:
|
case Type::Photo:
|
||||||
case Type::Video:
|
case Type::Video:
|
||||||
case Type::PhotoVideo: // #TODO stories
|
case Type::PhotoVideo:
|
||||||
case Type::RoundFile: {
|
case Type::RoundFile: {
|
||||||
auto itemHeight = _itemHeight + st::infoMediaSkip;
|
auto itemHeight = _itemHeight + st::infoMediaSkip;
|
||||||
auto index = 0;
|
auto index = 0;
|
||||||
|
|
|
@ -32,6 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
#include "history/view/history_view_cursor_state.h"
|
#include "history/view/history_view_cursor_state.h"
|
||||||
#include "history/view/history_view_service_message.h"
|
#include "history/view/history_view_service_message.h"
|
||||||
|
#include "media/stories/media_stories_controller.h" // ...TogglePinnedToast.
|
||||||
#include "window/window_session_controller.h"
|
#include "window/window_session_controller.h"
|
||||||
#include "window/window_peer_menu.h"
|
#include "window/window_peer_menu.h"
|
||||||
#include "ui/widgets/popup_menu.h"
|
#include "ui/widgets/popup_menu.h"
|
||||||
|
@ -55,6 +56,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "boxes/peer_list_controllers.h"
|
#include "boxes/peer_list_controllers.h"
|
||||||
#include "core/file_utilities.h"
|
#include "core/file_utilities.h"
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
|
#include "ui/toast/toast.h"
|
||||||
#include "styles/style_overview.h"
|
#include "styles/style_overview.h"
|
||||||
#include "styles/style_info.h"
|
#include "styles/style_info.h"
|
||||||
#include "styles/style_layers.h"
|
#include "styles/style_layers.h"
|
||||||
|
@ -258,6 +260,7 @@ 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::ToggleStoryPin: toggleStoryPinSelected(); return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,6 +338,7 @@ auto ListWidget::collectSelectedItems() const -> SelectedItems {
|
||||||
auto result = SelectedItem(item->globalId());
|
auto result = SelectedItem(item->globalId());
|
||||||
result.canDelete = selection.canDelete;
|
result.canDelete = selection.canDelete;
|
||||||
result.canForward = selection.canForward;
|
result.canForward = selection.canForward;
|
||||||
|
result.canToggleStoryPin = selection.canToggleStoryPin;
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
auto transformation = [&](const auto &item) {
|
auto transformation = [&](const auto &item) {
|
||||||
|
@ -349,6 +353,12 @@ auto ListWidget::collectSelectedItems() const -> SelectedItems {
|
||||||
std::back_inserter(items.list),
|
std::back_inserter(items.list),
|
||||||
transformation);
|
transformation);
|
||||||
}
|
}
|
||||||
|
if (_controller->storiesPeer() && items.list.size() > 1) {
|
||||||
|
// Don't allow forwarding more than one story.
|
||||||
|
for (auto &entry : items.list) {
|
||||||
|
entry.canForward = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1126,6 +1136,43 @@ void ListWidget::deleteSelected() {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ListWidget::toggleStoryPinSelected() {
|
||||||
|
auto list = std::vector<FullStoryId>();
|
||||||
|
const auto confirmed = crl::guard(this, [=] {
|
||||||
|
clearSelected();
|
||||||
|
});
|
||||||
|
for (const auto &item : collectSelectedItems().list) {
|
||||||
|
const auto id = item.globalId.itemId;
|
||||||
|
if (IsStoryMsgId(id.msg)) {
|
||||||
|
list.push_back({ id.peer, StoryIdFromMsgId(id.msg) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const auto count = int(list.size());
|
||||||
|
const auto pin = (_controller->storiesTab() == Stories::Tab::Archive);
|
||||||
|
const auto controller = _controller;
|
||||||
|
const auto sure = [=](Fn<void()> close) {
|
||||||
|
controller->session().data().stories().togglePinnedList(list, pin);
|
||||||
|
controller->showToast(
|
||||||
|
::Media::Stories::PrepareTogglePinnedToast(count, pin));
|
||||||
|
close();
|
||||||
|
confirmed();
|
||||||
|
};
|
||||||
|
const auto session = &_controller->session();
|
||||||
|
const auto onePhrase = pin
|
||||||
|
? tr::lng_stories_save_sure
|
||||||
|
: tr::lng_stories_archive_sure;
|
||||||
|
const auto manyPhrase = pin
|
||||||
|
? tr::lng_stories_save_sure_many
|
||||||
|
: tr::lng_stories_archive_sure_many;
|
||||||
|
_controller->parentController()->show(Ui::MakeConfirmBox({
|
||||||
|
.text = (count == 1
|
||||||
|
? onePhrase()
|
||||||
|
: manyPhrase(lt_count, rpl::single(count) | tr::to_count())),
|
||||||
|
.confirmed = sure,
|
||||||
|
.confirmText = tr::lng_box_ok(),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
void ListWidget::deleteItem(GlobalMsgId globalId) {
|
void ListWidget::deleteItem(GlobalMsgId globalId) {
|
||||||
if (const auto item = MessageByGlobalId(globalId)) {
|
if (const auto item = MessageByGlobalId(globalId)) {
|
||||||
auto items = SelectedItems(_provider->type());
|
auto items = SelectedItems(_provider->type());
|
||||||
|
@ -1134,7 +1181,6 @@ void ListWidget::deleteItem(GlobalMsgId globalId) {
|
||||||
item,
|
item,
|
||||||
FullSelection);
|
FullSelection);
|
||||||
items.list.back().canDelete = selectionData.canDelete;
|
items.list.back().canDelete = selectionData.canDelete;
|
||||||
items.list.back().canForward = selectionData.canForward;
|
|
||||||
deleteItems(std::move(items));
|
deleteItems(std::move(items));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1180,6 +1226,33 @@ void ListWidget::deleteItems(SelectedItems &&items, Fn<void()> confirmed) {
|
||||||
.confirmText = tr::lng_box_delete(tr::now),
|
.confirmText = tr::lng_box_delete(tr::now),
|
||||||
.confirmStyle = &st::attentionBoxButton,
|
.confirmStyle = &st::attentionBoxButton,
|
||||||
})));
|
})));
|
||||||
|
} else if (_controller->storiesPeer()) {
|
||||||
|
auto list = std::vector<FullStoryId>();
|
||||||
|
for (const auto &item : items.list) {
|
||||||
|
const auto id = item.globalId.itemId;
|
||||||
|
if (IsStoryMsgId(id.msg)) {
|
||||||
|
list.push_back({ id.peer, StoryIdFromMsgId(id.msg) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const auto session = &_controller->session();
|
||||||
|
const auto sure = [=](Fn<void()> close) {
|
||||||
|
session->data().stories().deleteList(list);
|
||||||
|
close();
|
||||||
|
if (confirmed) {
|
||||||
|
confirmed();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const auto count = int(list.size());
|
||||||
|
window->show(Ui::MakeConfirmBox({
|
||||||
|
.text = (count == 1
|
||||||
|
? tr::lng_stories_delete_one_sure()
|
||||||
|
: tr::lng_stories_delete_sure(
|
||||||
|
lt_count,
|
||||||
|
rpl::single(count) | tr::to_count())),
|
||||||
|
.confirmed = sure,
|
||||||
|
.confirmText = tr::lng_selected_delete(),
|
||||||
|
.confirmStyle = &st::attentionBoxButton,
|
||||||
|
}));
|
||||||
} else if (auto list = collectSelectedIds(items); !list.empty()) {
|
} else if (auto list = collectSelectedIds(items); !list.empty()) {
|
||||||
auto box = Box<DeleteMessagesBox>(
|
auto box = Box<DeleteMessagesBox>(
|
||||||
&_controller->session(),
|
&_controller->session(),
|
||||||
|
|
|
@ -189,6 +189,7 @@ private:
|
||||||
void forwardItem(GlobalMsgId globalId);
|
void forwardItem(GlobalMsgId globalId);
|
||||||
void forwardItems(MessageIdsList &&items);
|
void forwardItems(MessageIdsList &&items);
|
||||||
void deleteSelected();
|
void deleteSelected();
|
||||||
|
void toggleStoryPinSelected();
|
||||||
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 applyItemSelection(
|
void applyItemSelection(
|
||||||
|
|
|
@ -61,7 +61,7 @@ Type Provider::type() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Provider::hasSelectRestriction() {
|
bool Provider::hasSelectRestriction() {
|
||||||
return true; // #TODO stories
|
return !_peer->isSelf();
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<bool> Provider::hasSelectRestrictionChanges() {
|
rpl::producer<bool> Provider::hasSelectRestrictionChanges() {
|
||||||
|
@ -312,8 +312,10 @@ ListItemSelectionData Provider::computeSelectionData(
|
||||||
not_null<const HistoryItem*> item,
|
not_null<const HistoryItem*> item,
|
||||||
TextSelection selection) {
|
TextSelection selection) {
|
||||||
auto result = ListItemSelectionData(selection);
|
auto result = ListItemSelectionData(selection);
|
||||||
result.canDelete = item->canDelete();
|
const auto peer = item->history()->peer;
|
||||||
result.canForward = item->allowsForward();
|
result.canDelete = peer->isSelf();
|
||||||
|
result.canForward = peer->isSelf();
|
||||||
|
result.canToggleStoryPin = peer->isSelf();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,9 +336,10 @@ void Provider::applyDragSelection(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto &layoutItem : _layouts) {
|
for (auto &layoutItem : _layouts) {
|
||||||
const auto id = StoryIdToMsgId(layoutItem.first);
|
const auto storyId = layoutItem.first;
|
||||||
|
const auto id = StoryIdToMsgId(storyId);
|
||||||
if (id <= fromId && id > tillId) {
|
if (id <= fromId && id > tillId) {
|
||||||
const auto i = _items.find(id);
|
const auto i = _items.find(storyId);
|
||||||
Assert(i != end(_items));
|
Assert(i != end(_items));
|
||||||
const auto item = i->second.get();
|
const auto item = i->second.get();
|
||||||
ChangeItemSelection(
|
ChangeItemSelection(
|
||||||
|
|
|
@ -1309,21 +1309,7 @@ void Controller::togglePinnedRequested(bool pinned) {
|
||||||
moveFromShown();
|
moveFromShown();
|
||||||
}
|
}
|
||||||
story->owner().stories().togglePinnedList({ story->fullId() }, pinned);
|
story->owner().stories().togglePinnedList({ story->fullId() }, pinned);
|
||||||
uiShow()->showToast({
|
uiShow()->showToast(PrepareTogglePinnedToast(1, pinned));
|
||||||
.text = (pinned
|
|
||||||
? tr::lng_stories_save_done(
|
|
||||||
tr::now,
|
|
||||||
Ui::Text::Bold).append(
|
|
||||||
'\n').append(
|
|
||||||
tr::lng_stories_save_done_about(tr::now))
|
|
||||||
: tr::lng_stories_archive_done(
|
|
||||||
tr::now,
|
|
||||||
Ui::Text::WithEntities)),
|
|
||||||
.st = &st::storiesActionToast,
|
|
||||||
.duration = (pinned
|
|
||||||
? Data::Stories::kPinnedToastDuration
|
|
||||||
: Ui::Toast::kDefaultDuration),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::moveFromShown() {
|
void Controller::moveFromShown() {
|
||||||
|
@ -1375,4 +1361,34 @@ void Controller::startReactionAnimation(
|
||||||
}, layer->lifetime());
|
}, layer->lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ui::Toast::Config PrepareTogglePinnedToast(int count, bool pinned) {
|
||||||
|
return {
|
||||||
|
.text = (pinned
|
||||||
|
? (count == 1
|
||||||
|
? tr::lng_stories_save_done(
|
||||||
|
tr::now,
|
||||||
|
Ui::Text::Bold)
|
||||||
|
: tr::lng_stories_save_done_many(
|
||||||
|
tr::now,
|
||||||
|
lt_count,
|
||||||
|
count,
|
||||||
|
Ui::Text::Bold)).append(
|
||||||
|
'\n').append(
|
||||||
|
tr::lng_stories_save_done_about(tr::now))
|
||||||
|
: (count == 1
|
||||||
|
? tr::lng_stories_archive_done(
|
||||||
|
tr::now,
|
||||||
|
Ui::Text::WithEntities)
|
||||||
|
: tr::lng_stories_archive_done_many(
|
||||||
|
tr::now,
|
||||||
|
lt_count,
|
||||||
|
count,
|
||||||
|
Ui::Text::WithEntities))),
|
||||||
|
.st = &st::storiesActionToast,
|
||||||
|
.duration = (pinned
|
||||||
|
? Data::Stories::kPinnedToastDuration
|
||||||
|
: Ui::Toast::kDefaultDuration),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Media::Stories
|
} // namespace Media::Stories
|
||||||
|
|
|
@ -34,6 +34,10 @@ struct MessageSendingAnimationFrom;
|
||||||
class EmojiFlyAnimation;
|
class EmojiFlyAnimation;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
|
namespace Ui::Toast {
|
||||||
|
struct Config;
|
||||||
|
} // namespace Ui::Toast
|
||||||
|
|
||||||
namespace Main {
|
namespace Main {
|
||||||
class Session;
|
class Session;
|
||||||
} // namespace Main
|
} // namespace Main
|
||||||
|
@ -253,4 +257,8 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] Ui::Toast::Config PrepareTogglePinnedToast(
|
||||||
|
int count,
|
||||||
|
bool pinned);
|
||||||
|
|
||||||
} // namespace Media::Stories
|
} // namespace Media::Stories
|
||||||
|
|
Loading…
Add table
Reference in a new issue