Display online count in the info profile section.

This commit is contained in:
John Preston 2017-10-22 15:07:57 +03:00
parent 508fa14385
commit 856ca22aad
13 changed files with 229 additions and 45 deletions

View File

@ -20,6 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/ */
#include "boxes/peer_list_box.h" #include "boxes/peer_list_box.h"
#include <rpl/range.h>
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "styles/style_dialogs.h" #include "styles/style_dialogs.h"
#include "styles/style_widgets.h" #include "styles/style_widgets.h"
@ -230,6 +231,10 @@ void PeerListController::peerListSearchRefreshRows() {
delegate()->peerListRefreshRows(); delegate()->peerListRefreshRows();
} }
rpl::producer<int> PeerListController::onlineCountValue() const {
return rpl::single(0);
}
void PeerListController::setDescriptionText(const QString &text) { void PeerListController::setDescriptionText(const QString &text) {
if (text.isEmpty()) { if (text.isEmpty()) {
setDescription(nullptr); setDescription(nullptr);
@ -308,6 +313,7 @@ bool PeerListRow::checked() const {
void PeerListRow::setCustomStatus(const QString &status) { void PeerListRow::setCustomStatus(const QString &status) {
setStatusText(status); setStatusText(status);
_statusType = StatusType::Custom; _statusType = StatusType::Custom;
_statusValidTill = 0;
} }
void PeerListRow::clearCustomStatus() { void PeerListRow::clearCustomStatus() {
@ -320,12 +326,15 @@ void PeerListRow::refreshStatus() {
return; return;
} }
_statusType = StatusType::LastSeen; _statusType = StatusType::LastSeen;
_statusValidTill = 0;
if (auto user = peer()->asUser()) { if (auto user = peer()->asUser()) {
auto time = unixtime(); auto time = unixtime();
setStatusText(App::onlineText(user, time)); setStatusText(App::onlineText(user, time));
if (App::onlineColorUse(user, time)) { if (App::onlineColorUse(user, time)) {
_statusType = StatusType::Online; _statusType = StatusType::Online;
} }
_statusValidTill = getms()
+ App::onlineWillChangeIn(user, time);
} else if (auto chat = peer()->asChat()) { } else if (auto chat = peer()->asChat()) {
if (!chat->amIn()) { if (!chat->amIn()) {
setStatusText(lang(lng_chat_status_unaccessible)); setStatusText(lang(lng_chat_status_unaccessible));
@ -341,6 +350,10 @@ void PeerListRow::refreshStatus() {
} }
} }
TimeMs PeerListRow::refreshStatusTime() const {
return _statusValidTill;
}
void PeerListRow::refreshName(const style::PeerListItem &st) { void PeerListRow::refreshName(const style::PeerListItem &st) {
if (!_initialized) { if (!_initialized) {
return; return;
@ -505,6 +518,7 @@ PeerListContent::PeerListContent(
invalidatePixmapsCache(); invalidatePixmapsCache();
} }
}); });
_repaintByStatus.setCallback([this] { update(); });
} }
void PeerListContent::appendRow(std::unique_ptr<PeerListRow> row) { void PeerListContent::appendRow(std::unique_ptr<PeerListRow> row) {
@ -773,15 +787,18 @@ void PeerListContent::clearSearchRows() {
} }
void PeerListContent::paintEvent(QPaintEvent *e) { void PeerListContent::paintEvent(QPaintEvent *e) {
QRect r(e->rect());
Painter p(this); Painter p(this);
p.fillRect(r, _st.item.button.textBg); auto clip = e->rect();
p.fillRect(clip, _st.item.button.textBg);
auto repaintByStatusAfter = _repaintByStatus.remainingTime();
auto repaintAfterMin = repaintByStatusAfter;
auto rowsTopCached = rowsTop(); auto rowsTopCached = rowsTop();
auto ms = getms(); auto ms = getms();
auto yFrom = r.y() - rowsTopCached; auto yFrom = clip.y() - rowsTopCached;
auto yTo = r.y() + r.height() - rowsTopCached; auto yTo = clip.y() + clip.height() - rowsTopCached;
p.translate(0, rowsTopCached); p.translate(0, rowsTopCached);
auto count = shownRowsCount(); auto count = shownRowsCount();
if (count > 0) { if (count > 0) {
@ -789,10 +806,19 @@ void PeerListContent::paintEvent(QPaintEvent *e) {
auto to = ceilclamp(yTo, _rowHeight, 0, count); auto to = ceilclamp(yTo, _rowHeight, 0, count);
p.translate(0, from * _rowHeight); p.translate(0, from * _rowHeight);
for (auto index = from; index != to; ++index) { for (auto index = from; index != to; ++index) {
paintRow(p, ms, RowIndex(index)); auto repaintAfter = paintRow(p, ms, RowIndex(index));
if (repaintAfter >= 0
&& (repaintAfterMin < 0
|| repaintAfterMin > repaintAfter)) {
repaintAfterMin = repaintAfter;
}
p.translate(0, _rowHeight); p.translate(0, _rowHeight);
} }
} }
if (repaintAfterMin != repaintByStatusAfter) {
Assert(repaintAfterMin >= 0);
_repaintByStatus.callOnce(repaintAfterMin);
}
} }
int PeerListContent::resizeGetHeight(int newWidth) { int PeerListContent::resizeGetHeight(int newWidth) {
@ -894,11 +920,17 @@ void PeerListContent::setPressed(Selected pressed) {
_pressed = pressed; _pressed = pressed;
} }
void PeerListContent::paintRow(Painter &p, TimeMs ms, RowIndex index) { TimeMs PeerListContent::paintRow(Painter &p, TimeMs ms, RowIndex index) {
auto row = getRow(index); auto row = getRow(index);
Assert(row != nullptr); Assert(row != nullptr);
row->lazyInitialize(_st.item); row->lazyInitialize(_st.item);
auto refreshStatusAt = row->refreshStatusTime();
if (refreshStatusAt >= 0 && ms >= refreshStatusAt) {
row->refreshStatus();
refreshStatusAt = row->refreshStatusTime();
}
auto peer = row->peer(); auto peer = row->peer();
auto user = peer->asUser(); auto user = peer->asUser();
auto active = (_pressed.index.value >= 0) ? _pressed : _selected; auto active = (_pressed.index.value >= 0) ? _pressed : _selected;
@ -968,6 +1000,7 @@ void PeerListContent::paintRow(Painter &p, TimeMs ms, RowIndex index) {
} else { } else {
row->paintStatusText(p, _st.item, _st.item.statusPosition.x(), _st.item.statusPosition.y(), statusw, width(), selected); row->paintStatusText(p, _st.item, _st.item.statusPosition.x(), _st.item.statusPosition.y(), statusw, width(), selected);
} }
return (refreshStatusAt - ms);
} }
void PeerListContent::selectSkip(int direction) { void PeerListContent::selectSkip(int direction) {

View File

@ -112,6 +112,7 @@ public:
Custom, Custom,
}; };
void refreshStatus(); void refreshStatus();
TimeMs refreshStatusTime() const;
void setAbsoluteIndex(int index) { void setAbsoluteIndex(int index) {
_absoluteIndex = index; _absoluteIndex = index;
@ -199,6 +200,7 @@ private:
Text _name; Text _name;
Text _status; Text _status;
StatusType _statusType = StatusType::Online; StatusType _statusType = StatusType::Online;
TimeMs _statusValidTill = 0;
OrderedSet<QChar> _nameFirstChars; OrderedSet<QChar> _nameFirstChars;
int _absoluteIndex = -1; int _absoluteIndex = -1;
State _disabledState = State::Active; State _disabledState = State::Active;
@ -237,7 +239,7 @@ public:
virtual int peerListFullRowsCount() = 0; virtual int peerListFullRowsCount() = 0;
virtual PeerListRow *peerListFindRow(PeerListRowId id) = 0; virtual PeerListRow *peerListFindRow(PeerListRowId id) = 0;
virtual void peerListSortRows(base::lambda<bool(PeerListRow &a, PeerListRow &b)> compare) = 0; virtual void peerListSortRows(base::lambda<bool(PeerListRow &a, PeerListRow &b)> compare) = 0;
virtual void peerListPartitionRows(base::lambda<bool(PeerListRow &a)> border) = 0; virtual int peerListPartitionRows(base::lambda<bool(PeerListRow &a)> border) = 0;
template <typename PeerDataRange> template <typename PeerDataRange>
void peerListAddSelectedRows(PeerDataRange &&range) { void peerListAddSelectedRows(PeerDataRange &&range) {
@ -324,6 +326,8 @@ public:
void peerListSearchAddRow(not_null<PeerData*> peer) override; void peerListSearchAddRow(not_null<PeerData*> peer) override;
void peerListSearchRefreshRows() override; void peerListSearchRefreshRows() override;
virtual rpl::producer<int> onlineCountValue() const;
rpl::lifetime &lifetime() { rpl::lifetime &lifetime() {
return _lifetime; return _lifetime;
} }
@ -479,7 +483,7 @@ private:
RowIndex findRowIndex(not_null<PeerListRow*> row, RowIndex hint = RowIndex()); RowIndex findRowIndex(not_null<PeerListRow*> row, RowIndex hint = RowIndex());
QRect getActionRect(not_null<PeerListRow*> row, RowIndex index) const; QRect getActionRect(not_null<PeerListRow*> row, RowIndex index) const;
void paintRow(Painter &p, TimeMs ms, RowIndex index); TimeMs paintRow(Painter &p, TimeMs ms, RowIndex index);
void addRowEntry(not_null<PeerListRow*> row); void addRowEntry(not_null<PeerListRow*> row);
void addToSearchIndex(not_null<PeerListRow*> row); void addToSearchIndex(not_null<PeerListRow*> row);
@ -535,6 +539,7 @@ private:
QPoint _lastMousePosition; QPoint _lastMousePosition;
std::vector<std::unique_ptr<PeerListRow>> _searchRows; std::vector<std::unique_ptr<PeerListRow>> _searchRows;
base::Timer _repaintByStatus;
}; };
@ -619,16 +624,19 @@ public:
}); });
}); });
} }
void peerListPartitionRows( int peerListPartitionRows(
base::lambda<bool(PeerListRow &a)> border) override { base::lambda<bool(PeerListRow &a)> border) override {
_content->reorderRows([border = std::move(border)]( auto result = 0;
_content->reorderRows([border = std::move(border), &result](
auto &&begin, auto &&begin,
auto &&end) { auto &&end) {
std::stable_partition(begin, end, [&border]( auto edge = std::stable_partition(begin, end, [&border](
auto &&current) { auto &&current) {
return border(*current); return border(*current);
}); });
result = (edge - begin);
}); });
return result;
} }
protected: protected:

View File

@ -143,7 +143,7 @@ auto OnlineStatusText(int count) {
}; };
auto ChatStatusText(int fullCount, int onlineCount, bool isGroup) { auto ChatStatusText(int fullCount, int onlineCount, bool isGroup) {
if (onlineCount > 0 && onlineCount <= fullCount) { if (onlineCount > 1 && onlineCount <= fullCount) {
return lng_chat_status_members_online( return lng_chat_status_members_online(
lt_members_count, MembersStatusText(fullCount), lt_members_count, MembersStatusText(fullCount),
lt_online_count, OnlineStatusText(onlineCount)); lt_online_count, OnlineStatusText(onlineCount));

View File

@ -129,6 +129,7 @@ object_ptr<Ui::RpWidget> InnerWidget::setupContent(
: mapFromGlobal(_members->mapToGlobal({ 0, request.ymax })).y(); : mapFromGlobal(_members->mapToGlobal({ 0, request.ymax })).y();
_scrollToRequests.fire({ min, max }); _scrollToRequests.fire({ min, max });
}, _members->lifetime()); }, _members->lifetime());
_cover->setOnlineCount(_members->onlineCountValue());
} }
return std::move(result); return std::move(result);
} }

View File

@ -88,6 +88,10 @@ int Members::desiredHeight() const {
return qMax(height(), desired); return qMax(height(), desired);
} }
rpl::producer<int> Members::onlineCountValue() const {
return _listController->onlineCountValue();
}
object_ptr<Ui::FlatLabel> Members::setupHeader() { object_ptr<Ui::FlatLabel> Members::setupHeader() {
auto result = object_ptr<Ui::FlatLabel>( auto result = object_ptr<Ui::FlatLabel>(
_labelWrap, _labelWrap,
@ -183,7 +187,9 @@ object_ptr<Members::ListWidget> Members::setupList(
result->heightValue() result->heightValue()
| rpl::start_with_next([parent](int listHeight) { | rpl::start_with_next([parent](int listHeight) {
auto newHeight = (listHeight > st::membersMarginBottom) auto newHeight = (listHeight > st::membersMarginBottom)
? (st::infoMembersHeader + listHeight) ? (st::infoMembersHeader
+ listHeight
+ st::membersMarginBottom)
: 0; : 0;
parent->resize(parent->width(), newHeight); parent->resize(parent->width(), newHeight);
}, result->lifetime()); }, result->lifetime());

View File

@ -57,6 +57,7 @@ public:
} }
int desiredHeight() const; int desiredHeight() const;
rpl::producer<int> onlineCountValue() const;
protected: protected:
void visibleTopBottomUpdated( void visibleTopBottomUpdated(

View File

@ -20,6 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/ */
#include "info/profile/info_profile_members_controllers.h" #include "info/profile/info_profile_members_controllers.h"
#include <rpl/variable.h>
#include "profile/profile_channel_controllers.h" #include "profile/profile_channel_controllers.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "apiwrap.h" #include "apiwrap.h"
@ -31,6 +32,8 @@ namespace Info {
namespace Profile { namespace Profile {
namespace { namespace {
constexpr auto kSortByOnlineDelay = TimeMs(1000);
class ChatMembersController class ChatMembersController
: public PeerListController : public PeerListController
, private base::Subscriber { , private base::Subscriber {
@ -42,13 +45,23 @@ public:
void prepare() override; void prepare() override;
void rowClicked(not_null<PeerListRow*> row) override; void rowClicked(not_null<PeerListRow*> row) override;
rpl::producer<int> onlineCountValue() const override {
return _onlineCount.value();
}
private: private:
void rebuildRows(); void rebuildRows();
void refreshOnlineCount();
std::unique_ptr<PeerListRow> createRow(not_null<UserData*> user); std::unique_ptr<PeerListRow> createRow(not_null<UserData*> user);
void sortByOnline();
void sortByOnlineDelayed();
not_null<Window::Controller*> _window; not_null<Window::Controller*> _window;
not_null<ChatData*> _chat; not_null<ChatData*> _chat;
base::Timer _sortByOnlineTimer;
rpl::variable<int> _onlineCount = 0;
}; };
ChatMembersController::ChatMembersController( ChatMembersController::ChatMembersController(
@ -57,6 +70,7 @@ ChatMembersController::ChatMembersController(
: PeerListController() : PeerListController()
, _window(window) , _window(window)
, _chat(chat) { , _chat(chat) {
_sortByOnlineTimer.setCallback([this] { sortByOnline(); });
} }
void ChatMembersController::prepare() { void ChatMembersController::prepare() {
@ -77,13 +91,30 @@ void ChatMembersController::prepare() {
rebuildRows(); rebuildRows();
} }
} else if (update.flags & UpdateFlag::UserOnlineChanged) { } else if (update.flags & UpdateFlag::UserOnlineChanged) {
if (auto row = delegate()->peerListFindRow(
update.peer->id)) {
row->refreshStatus();
sortByOnlineDelayed();
}
}
}));
}
void ChatMembersController::sortByOnlineDelayed() {
if (!_sortByOnlineTimer.isActive()) {
_sortByOnlineTimer.callOnce(kSortByOnlineDelay);
}
}
void ChatMembersController::sortByOnline() {
auto now = unixtime(); auto now = unixtime();
delegate()->peerListSortRows([now](const PeerListRow &a, const PeerListRow &b) { delegate()->peerListSortRows([now](
const PeerListRow &a,
const PeerListRow &b) {
return App::onlineForSort(a.peer()->asUser(), now) > return App::onlineForSort(a.peer()->asUser(), now) >
App::onlineForSort(b.peer()->asUser(), now); App::onlineForSort(b.peer()->asUser(), now);
}); });
} refreshOnlineCount();
}));
} }
void ChatMembersController::rebuildRows() { void ChatMembersController::rebuildRows() {
@ -108,10 +139,26 @@ void ChatMembersController::rebuildRows() {
delegate()->peerListAppendRow(std::move(row)); delegate()->peerListAppendRow(std::move(row));
} }
}); });
refreshOnlineCount();
delegate()->peerListRefreshRows(); delegate()->peerListRefreshRows();
} }
void ChatMembersController::refreshOnlineCount() {
auto now = unixtime();
auto left = 0, right = delegate()->peerListFullRowsCount();
while (right > left) {
auto middle = (left + right) / 2;
auto row = delegate()->peerListRowAt(middle);
if (App::onlineColorUse(row->peer()->asUser(), now)) {
left = middle + 1;
} else {
right = middle;
}
}
_onlineCount = left;
}
std::unique_ptr<PeerListRow> ChatMembersController::createRow(not_null<UserData*> user) { std::unique_ptr<PeerListRow> ChatMembersController::createRow(not_null<UserData*> user) {
return std::make_unique<PeerListRow>(user); return std::make_unique<PeerListRow>(user);
} }

View File

@ -80,6 +80,7 @@ void ParticipantsBoxController::sortByOnlineDelayed() {
void ParticipantsBoxController::sortByOnline() { void ParticipantsBoxController::sortByOnline() {
if (_role != Role::Profile if (_role != Role::Profile
|| _channel->membersCount() > Global::ChatSizeMax()) { || _channel->membersCount() > Global::ChatSizeMax()) {
_onlineCount = 0;
return; return;
} }
auto now = unixtime(); auto now = unixtime();
@ -89,6 +90,25 @@ void ParticipantsBoxController::sortByOnline() {
return App::onlineForSort(a.peer()->asUser(), now) > return App::onlineForSort(a.peer()->asUser(), now) >
App::onlineForSort(b.peer()->asUser(), now); App::onlineForSort(b.peer()->asUser(), now);
}); });
refreshOnlineCount();
}
void ParticipantsBoxController::refreshOnlineCount() {
Expects(_role == Role::Profile);
Expects(_channel->membersCount() <= Global::ChatSizeMax());
auto now = unixtime();
auto left = 0, right = delegate()->peerListFullRowsCount();
while (right > left) {
auto middle = (left + right) / 2;
auto row = delegate()->peerListRowAt(middle);
if (App::onlineColorUse(row->peer()->asUser(), now)) {
left = middle + 1;
} else {
right = middle;
}
}
_onlineCount = left;
} }
std::unique_ptr<PeerListSearchController> std::unique_ptr<PeerListSearchController>

View File

@ -20,6 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/ */
#pragma once #pragma once
#include <rpl/variable.h>
#include "boxes/peer_list_box.h" #include "boxes/peer_list_box.h"
#include "mtproto/sender.h" #include "mtproto/sender.h"
#include "base/timer.h" #include "base/timer.h"
@ -81,6 +82,10 @@ public:
template <typename Callback> template <typename Callback>
static void HandleParticipant(const MTPChannelParticipant &participant, Role role, not_null<Additional*> additional, Callback callback); static void HandleParticipant(const MTPChannelParticipant &participant, Role role, not_null<Additional*> additional, Callback callback);
rpl::producer<int> onlineCountValue() const override {
return _onlineCount.value();
}
protected: protected:
virtual std::unique_ptr<PeerListRow> createRow(not_null<UserData*> user) const; virtual std::unique_ptr<PeerListRow> createRow(not_null<UserData*> user) const;
@ -102,6 +107,7 @@ private:
bool removeRow(not_null<UserData*> user); bool removeRow(not_null<UserData*> user);
void refreshCustomStatus(not_null<PeerListRow*> row) const; void refreshCustomStatus(not_null<PeerListRow*> row) const;
bool feedMegagroupLastParticipants(); bool feedMegagroupLastParticipants();
void refreshOnlineCount();
not_null<Window::Controller*> _window; not_null<Window::Controller*> _window;
not_null<ChannelData*> _channel; not_null<ChannelData*> _channel;
@ -114,6 +120,7 @@ private:
QPointer<PeerListBox> _addBox; QPointer<PeerListBox> _addBox;
base::Timer _sortByOnlineTimer; base::Timer _sortByOnlineTimer;
rpl::variable<int> _onlineCount = 0;
}; };

View File

@ -26,37 +26,24 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
namespace rpl { namespace rpl {
template <typename Type> template <typename Type>
class variable { class variable final {
public: public:
variable() : _data{} { variable() : _data{} {
} }
variable(const variable &other) = default;
variable(variable &&other) = default;
variable &operator=(const variable &other) = default;
variable &operator=(variable &&other) = default;
variable(const Type &data) : _data(data) {
}
variable(Type &&data) : _data(std::move(data)) {
}
variable &operator=(const Type &data) {
return assign(data);
}
template < template <
typename OtherType, typename OtherType,
typename = std::enable_if_t< typename = std::enable_if_t<
std::is_constructible_v<Type, OtherType&&> std::is_constructible_v<Type, OtherType&&>>>
&& !std::is_same_v<std::decay_t<OtherType>, Type>>>
variable(OtherType &&data) : _data(std::forward<OtherType>(data)) { variable(OtherType &&data) : _data(std::forward<OtherType>(data)) {
} }
template < template <
typename OtherType, typename OtherType,
typename = std::enable_if_t< typename = std::enable_if_t<
std::is_assignable_v<Type, OtherType&&> std::is_assignable_v<Type&, OtherType&&>>>
&& !std::is_same_v<std::decay_t<OtherType>, Type>>>
variable &operator=(OtherType &&data) { variable &operator=(OtherType &&data) {
_lifetime.destroy();
return assign(std::forward<OtherType>(data)); return assign(std::forward<OtherType>(data));
} }
@ -65,11 +52,11 @@ public:
typename Error, typename Error,
typename Generator, typename Generator,
typename = std::enable_if_t< typename = std::enable_if_t<
std::is_assignable_v<Type, OtherType>>> std::is_assignable_v<Type&, OtherType>>>
variable(producer<OtherType, Error, Generator> &&stream) { variable(producer<OtherType, Error, Generator> &&stream) {
std::move(stream) std::move(stream)
| start_with_next([this](auto &&data) { | start_with_next([this](auto &&data) {
*this = std::forward<decltype(data)>(data); assign(std::forward<decltype(data)>(data));
}, _lifetime); }, _lifetime);
} }
@ -78,13 +65,13 @@ public:
typename Error, typename Error,
typename Generator, typename Generator,
typename = std::enable_if_t< typename = std::enable_if_t<
std::is_assignable_v<Type, OtherType>>> std::is_assignable_v<Type&, OtherType>>>
variable &operator=( variable &operator=(
producer<OtherType, Error, Generator> &&stream) { producer<OtherType, Error, Generator> &&stream) {
_lifetime.destroy(); _lifetime.destroy();
std::move(stream) std::move(stream)
| start_with_next([this](auto &&data) { | start_with_next([this](auto &&data) {
*this = std::forward<decltype(data)>(data); assign(std::forward<decltype(data)>(data));
}, _lifetime); }, _lifetime);
} }
@ -96,11 +83,39 @@ public:
} }
private: private:
template <typename A, typename B>
struct supports_equality_compare {
template <typename U, typename V>
static auto test(const U *u, const V *v)
-> decltype(*u == *v, details::true_t());
static details::false_t test(...);
static constexpr bool value
= (sizeof(test(
(std::decay_t<A>*)nullptr,
(std::decay_t<B>*)nullptr
)) == sizeof(details::true_t));
};
template <typename A, typename B>
static constexpr bool supports_equality_compare_v
= supports_equality_compare<A, B>::value;
template <typename OtherType> template <typename OtherType>
variable &assign(OtherType &&data) { variable &assign(OtherType &&data) {
_lifetime.destroy(); if constexpr (supports_equality_compare_v<Type, OtherType>) {
if (!(_data == data)) {
_data = std::forward<OtherType>(data); _data = std::forward<OtherType>(data);
_changes.fire_copy(_data); _changes.fire_copy(_data);
}
} else if constexpr (supports_equality_compare_v<Type, Type>) {
auto old = std::move(_data);
_data = std::forward<OtherType>(data);
if (!(_data == old)) {
_changes.fire_copy(_data);
}
} else {
_data = std::forward<OtherType>(data);
_changes.fire_copy(_data);
}
return *this; return *this;
} }

View File

@ -0,0 +1,45 @@
/*
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 "catch.hpp"
#include <rpl/rpl.h>
#include <string>
using namespace rpl;
TEST_CASE("basic variable tests", "[rpl::variable]") {
SECTION("simple test") {
auto sum = std::make_shared<int>(0);
{
auto var = variable<int>(1);
auto lifeftime = var.value()
| start_with_next([=](int value) {
*sum += value;
});
var = 1;
var = 11;
var = 111;
var = 111;
}
REQUIRE(*sum == 1 + 11 + 111);
}
}

View File

@ -28,7 +28,7 @@ else
#gyp --depth=. --generator-output=../.. -Goutput_dir=out Telegram.gyp --format=xcode-ninja #gyp --depth=. --generator-output=../.. -Goutput_dir=out Telegram.gyp --format=xcode-ninja
#gyp --depth=. --generator-output=../.. -Goutput_dir=out Telegram.gyp --format=xcode #gyp --depth=. --generator-output=../.. -Goutput_dir=out Telegram.gyp --format=xcode
# use patched gyp with Xcode project generator # use patched gyp with Xcode project generator
../../../Libraries/gyp/gyp --depth=. --generator-output=.. -Goutput_dir=../out -Gxcode_upgrade_check_project_version=900 -Dofficial_build_target=$BuildTarget Telegram.gyp --format=xcode ../../../Libraries/gyp/gyp --depth=. --generator-output=.. -Goutput_dir=../out -Gxcode_upgrade_check_project_version=910 -Dofficial_build_target=$BuildTarget Telegram.gyp --format=xcode
fi fi
cd ../.. cd ../..

View File

@ -126,6 +126,7 @@
'<(src_loc)/rpl/then.h', '<(src_loc)/rpl/then.h',
'<(src_loc)/rpl/type_erased.h', '<(src_loc)/rpl/type_erased.h',
'<(src_loc)/rpl/variable.h', '<(src_loc)/rpl/variable.h',
'<(src_loc)/rpl/variable_tests.cpp',
], ],
}], }],
} }