mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 06:07:06 +02:00
Show active stories in profile top bar.
This commit is contained in:
parent
738e20252e
commit
d2dd63e90a
9 changed files with 143 additions and 8 deletions
|
@ -505,6 +505,7 @@ DialogsStoriesList {
|
|||
full: DialogsStories;
|
||||
bg: color;
|
||||
readOpacity: double;
|
||||
fullClickable: int;
|
||||
}
|
||||
|
||||
dialogsStories: DialogsStories {
|
||||
|
@ -544,9 +545,11 @@ dialogsStoriesList: DialogsStoriesList {
|
|||
full: dialogsStoriesFull;
|
||||
bg: dialogsBg;
|
||||
readOpacity: 0.6;
|
||||
fullClickable: 0;
|
||||
}
|
||||
dialogsStoriesListInfo: DialogsStoriesList(dialogsStoriesList) {
|
||||
bg: transparent;
|
||||
fullClickable: 1;
|
||||
}
|
||||
dialogsStoriesListMine: DialogsStoriesList(dialogsStoriesListInfo) {
|
||||
readOpacity: 1.;
|
||||
|
|
|
@ -846,7 +846,7 @@ void List::updateSelected() {
|
|||
+ lastRightAdd)
|
||||
? (infiniteIndex - 1) // Last small part should still be clickable.
|
||||
: (startIndex + infiniteIndex >= endIndex)
|
||||
? -1
|
||||
? (_st.fullClickable ? (endIndex - 1) : -1)
|
||||
: infiniteIndex;
|
||||
const auto selected = (index < 0
|
||||
|| startIndex + index >= layout.itemsCount)
|
||||
|
|
|
@ -273,6 +273,11 @@ void ContentWidget::setViewport(
|
|||
}, _scroll->lifetime());
|
||||
}
|
||||
|
||||
auto ContentWidget::titleStories()
|
||||
-> rpl::producer<Dialogs::Stories::Content> {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ContentWidget::saveChanges(FnMut<void()> done) {
|
||||
done();
|
||||
}
|
||||
|
|
|
@ -11,6 +11,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/rp_widget.h"
|
||||
#include "info/info_wrap_widget.h"
|
||||
|
||||
namespace Dialogs::Stories {
|
||||
struct Content;
|
||||
} // namespace Dialogs::Stories
|
||||
|
||||
namespace Storage {
|
||||
enum class SharedMediaType : signed char;
|
||||
} // namespace Storage
|
||||
|
@ -88,6 +92,8 @@ public:
|
|||
}
|
||||
|
||||
[[nodiscard]] virtual rpl::producer<QString> title() = 0;
|
||||
[[nodiscard]] virtual auto titleStories()
|
||||
-> rpl::producer<Dialogs::Stories::Content>;
|
||||
|
||||
virtual void saveChanges(FnMut<void()> done);
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include <rpl/never.h>
|
||||
#include <rpl/merge.h>
|
||||
#include "dialogs/ui/dialogs_stories_content.h"
|
||||
#include "dialogs/ui/dialogs_stories_list.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "lang/lang_numbers_animation.h"
|
||||
#include "info/info_wrap_widget.h"
|
||||
|
@ -30,6 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_session.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_user.h"
|
||||
#include "styles/style_dialogs.h"
|
||||
#include "styles/style_info.h"
|
||||
|
||||
namespace Info {
|
||||
|
@ -88,9 +91,11 @@ void TopBar::setTitle(rpl::producer<QString> &&title) {
|
|||
object_ptr<Ui::FlatLabel>(this, std::move(title), _st.title),
|
||||
st::infoTopBarScale);
|
||||
_title->setDuration(st::infoTopBarDuration);
|
||||
_title->toggle(!selectionMode(), anim::type::instant);
|
||||
_title->toggle(
|
||||
!selectionMode() && !storiesTitle(),
|
||||
anim::type::instant);
|
||||
registerToggleControlCallback(_title.data(), [=] {
|
||||
return !selectionMode() && !searchMode();
|
||||
return !selectionMode() && !storiesTitle() && !searchMode();
|
||||
});
|
||||
|
||||
if (_back) {
|
||||
|
@ -309,12 +314,15 @@ int TopBar::resizeGetHeight(int newWidth) {
|
|||
void TopBar::updateControlsGeometry(int newWidth) {
|
||||
updateDefaultControlsGeometry(newWidth);
|
||||
updateSelectionControlsGeometry(newWidth);
|
||||
updateStoriesGeometry(newWidth);
|
||||
}
|
||||
|
||||
void TopBar::updateDefaultControlsGeometry(int newWidth) {
|
||||
auto right = 0;
|
||||
for (auto &button : _buttons) {
|
||||
if (!button) continue;
|
||||
if (!button) {
|
||||
continue;
|
||||
}
|
||||
button->moveToRight(right, 0, newWidth);
|
||||
right += button->width();
|
||||
}
|
||||
|
@ -362,6 +370,28 @@ void TopBar::updateSelectionControlsGeometry(int newWidth) {
|
|||
newWidth);
|
||||
}
|
||||
|
||||
void TopBar::updateStoriesGeometry(int newWidth) {
|
||||
if (!_stories) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto right = 0;
|
||||
for (auto &button : _buttons) {
|
||||
if (!button) {
|
||||
continue;
|
||||
}
|
||||
button->moveToRight(right, 0, newWidth);
|
||||
right += button->width();
|
||||
}
|
||||
const auto left = (_back ? _st.back.width : _st.titlePosition.x())
|
||||
- st::dialogsStories.left - st::dialogsStories.photoLeft;
|
||||
const auto top = st::dialogsStories.height
|
||||
- st::dialogsStoriesFull.height
|
||||
+ (_st.height - st::dialogsStories.height) / 2;
|
||||
_stories->resizeToWidth(newWidth - left - right);
|
||||
_stories->moveToLeft(left, top, newWidth);
|
||||
}
|
||||
|
||||
void TopBar::paintEvent(QPaintEvent *e) {
|
||||
auto p = QPainter(this);
|
||||
|
||||
|
@ -412,6 +442,60 @@ void TopBar::updateControlsVisibility(anim::type animated) {
|
|||
}
|
||||
}
|
||||
|
||||
void TopBar::setStories(rpl::producer<Dialogs::Stories::Content> content) {
|
||||
_storiesLifetime.destroy();
|
||||
if (content) {
|
||||
using namespace Dialogs::Stories;
|
||||
|
||||
auto last = std::move(
|
||||
content
|
||||
) | rpl::start_spawning(_storiesLifetime);
|
||||
delete _stories;
|
||||
|
||||
const auto stories = Ui::CreateChild<Ui::FadeWrap<List>>(
|
||||
this,
|
||||
object_ptr<List>(
|
||||
this,
|
||||
st::dialogsStoriesListInfo,
|
||||
rpl::duplicate(
|
||||
last
|
||||
) | rpl::filter([](const Content &content) {
|
||||
return !content.elements.empty();
|
||||
}),
|
||||
[] { return st::dialogsStories.height; }),
|
||||
st::infoTopBarScale);
|
||||
registerToggleControlCallback(
|
||||
stories,
|
||||
[this] { return _storiesCount > 0; });
|
||||
stories->toggle(false, anim::type::instant);
|
||||
stories->setDuration(st::infoTopBarDuration);
|
||||
_stories = stories;
|
||||
_stories->entity()->clicks(
|
||||
) | rpl::start_to_stream(_storyClicks, _stories->lifetime());
|
||||
if (_back) {
|
||||
_back->raise();
|
||||
}
|
||||
|
||||
rpl::duplicate(
|
||||
last
|
||||
) | rpl::start_with_next([=](const Content &content) {
|
||||
const auto count = int(content.elements.size());
|
||||
if (_storiesCount != count) {
|
||||
const auto was = (_storiesCount > 0);
|
||||
_storiesCount = count;
|
||||
const auto now = (_storiesCount > 0);
|
||||
if (was != now) {
|
||||
updateControlsVisibility(anim::type::normal);
|
||||
}
|
||||
updateControlsGeometry(width());
|
||||
}
|
||||
}, _storiesLifetime);
|
||||
} else {
|
||||
_storiesCount = 0;
|
||||
}
|
||||
updateControlsVisibility(anim::type::instant);
|
||||
}
|
||||
|
||||
void TopBar::setSelectedItems(SelectedItems &&items) {
|
||||
auto wasSelectionMode = selectionMode();
|
||||
_selectedItems = std::move(items);
|
||||
|
@ -550,6 +634,10 @@ bool TopBar::selectionMode() const {
|
|||
return !_selectedItems.list.empty();
|
||||
}
|
||||
|
||||
bool TopBar::storiesTitle() const {
|
||||
return _storiesCount > 0;
|
||||
}
|
||||
|
||||
bool TopBar::searchMode() const {
|
||||
return _searchModeAvailable && _searchModeEnabled;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,11 @@ namespace style {
|
|||
struct InfoTopBar;
|
||||
} // namespace style
|
||||
|
||||
namespace Dialogs::Stories {
|
||||
class List;
|
||||
struct Content;
|
||||
} // namespace Dialogs::Stories
|
||||
|
||||
namespace Window {
|
||||
class SessionNavigation;
|
||||
} // namespace Window
|
||||
|
@ -43,11 +48,15 @@ public:
|
|||
const style::InfoTopBar &st,
|
||||
SelectedItems &&items);
|
||||
|
||||
auto backRequest() const {
|
||||
[[nodiscard]] auto backRequest() const {
|
||||
return _backClicks.events();
|
||||
}
|
||||
[[nodiscard]] auto storyClicks() const {
|
||||
return _storyClicks.events();
|
||||
}
|
||||
|
||||
void setTitle(rpl::producer<QString> &&title);
|
||||
void setStories(rpl::producer<Dialogs::Stories::Content> content);
|
||||
void enableBackButton();
|
||||
void highlight();
|
||||
|
||||
|
@ -95,6 +104,7 @@ private:
|
|||
void updateControlsGeometry(int newWidth);
|
||||
void updateDefaultControlsGeometry(int newWidth);
|
||||
void updateSelectionControlsGeometry(int newWidth);
|
||||
void updateStoriesGeometry(int newWidth);
|
||||
Ui::FadeWrap<Ui::RpWidget> *pushButton(
|
||||
base::unique_qptr<Ui::RpWidget> button);
|
||||
void forceButtonVisibility(
|
||||
|
@ -104,9 +114,10 @@ private:
|
|||
void startHighlightAnimation();
|
||||
void updateControlsVisibility(anim::type animated);
|
||||
|
||||
bool selectionMode() const;
|
||||
bool searchMode() const;
|
||||
Ui::StringWithNumbers generateSelectedText() const;
|
||||
[[nodiscard]] bool selectionMode() const;
|
||||
[[nodiscard]] bool storiesTitle() const;
|
||||
[[nodiscard]] bool searchMode() const;
|
||||
[[nodiscard]] Ui::StringWithNumbers generateSelectedText() const;
|
||||
[[nodiscard]] bool computeCanDelete() const;
|
||||
[[nodiscard]] bool computeCanForward() const;
|
||||
void updateSelectionState();
|
||||
|
@ -147,6 +158,7 @@ private:
|
|||
QPointer<Ui::InputField> _searchField;
|
||||
|
||||
rpl::event_stream<> _backClicks;
|
||||
rpl::event_stream<uint64> _storyClicks;
|
||||
|
||||
SelectedItems _selectedItems;
|
||||
bool _canDelete = false;
|
||||
|
@ -157,6 +169,10 @@ private:
|
|||
QPointer<Ui::FadeWrap<Ui::IconButton>> _delete;
|
||||
rpl::event_stream<SelectionAction> _selectionActionRequests;
|
||||
|
||||
QPointer<Ui::FadeWrap<Dialogs::Stories::List>> _stories;
|
||||
rpl::lifetime _storiesLifetime;
|
||||
int _storiesCount = 0;
|
||||
|
||||
using UpdateCallback = Fn<bool(anim::type)>;
|
||||
std::map<QObject*, UpdateCallback> _updateControlCallbacks;
|
||||
|
||||
|
|
|
@ -303,6 +303,11 @@ void WrapWidget::createTopBar() {
|
|||
_controller->parentController()->closeThirdSection();
|
||||
});
|
||||
}
|
||||
_topBar->storyClicks() | rpl::start_with_next([=] {
|
||||
if (const auto peer = _controller->key().peer()) {
|
||||
_controller->parentController()->openPeerStories(peer->id);
|
||||
}
|
||||
}, _topBar->lifetime());
|
||||
if (wrapValue == Wrap::Layer) {
|
||||
auto close = _topBar->addButton(
|
||||
base::make_unique_q<Ui::IconButton>(
|
||||
|
@ -579,6 +584,7 @@ void WrapWidget::finishShowContent() {
|
|||
_content->setIsStackBottom(!hasStackHistory());
|
||||
if (_topBar) {
|
||||
_topBar->setTitle(_content->title());
|
||||
_topBar->setStories(_content->titleStories());
|
||||
}
|
||||
_desiredHeights.fire(desiredHeightForContent());
|
||||
_desiredShadowVisibilities.fire(_content->desiredShadowVisibility());
|
||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "info/profile/info_profile_widget.h"
|
||||
|
||||
#include "dialogs/ui/dialogs_stories_content.h"
|
||||
#include "info/profile/info_profile_inner_widget.h"
|
||||
#include "info/profile/info_profile_members.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
|
@ -105,7 +106,16 @@ rpl::producer<QString> Widget::title() {
|
|||
return tr::lng_info_group_title();
|
||||
}
|
||||
Unexpected("Bad peer type in Info::TitleValue()");
|
||||
}
|
||||
|
||||
rpl::producer<Dialogs::Stories::Content> Widget::titleStories() {
|
||||
const auto peer = controller()->key().peer();
|
||||
if (const auto user = peer->asUser()) {
|
||||
if (!user->isBot()) {
|
||||
return Dialogs::Stories::LastForPeer(user);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Widget::showInternal(not_null<ContentMemento*> memento) {
|
||||
|
|
|
@ -60,6 +60,7 @@ public:
|
|||
void setInnerFocus() override;
|
||||
|
||||
rpl::producer<QString> title() override;
|
||||
rpl::producer<Dialogs::Stories::Content> titleStories() override;
|
||||
|
||||
private:
|
||||
void saveState(not_null<Memento*> memento);
|
||||
|
|
Loading…
Add table
Reference in a new issue