Ejemplo n.º 1
0
bool MessagesSliceBuilder::removeFromChannel(ChannelId channelId) {
	for (auto i = _ids.begin(); i != _ids.end();) {
		if ((*i).fullId.channel == channelId) {
			i = _ids.erase(i);
			if (_fullCount) {
				--*_fullCount;
			}
		} else {
			++i;
		}
	}
	_skippedBefore = _skippedAfter = std::nullopt;
	checkInsufficient();
	return true;
}
rpl::producer<SparseIdsSlice> SharedMediaViewer(
		Storage::SharedMediaKey key,
		int limitBefore,
		int limitAfter) {
	Expects(IsServerMsgId(key.messageId) || (key.messageId == 0));
	Expects((key.messageId != 0) || (limitBefore == 0 && limitAfter == 0));

	return [=](auto consumer) {
		auto lifetime = rpl::lifetime();
		auto builder = lifetime.make_state<SparseIdsSliceBuilder>(
			key.messageId,
			limitBefore,
			limitAfter);
		auto requestMediaAround = [
			peer = App::peer(key.peerId),
			type = key.type
		](const SparseIdsSliceBuilder::AroundData &data) {
			Auth().api().requestSharedMedia(
				peer,
				type,
				data.aroundId,
				data.direction);
		};
		builder->insufficientAround(
		) | rpl::start_with_next(requestMediaAround, lifetime);

		auto pushNextSnapshot = [=] {
			consumer.put_next(builder->snapshot());
		};

		using SliceUpdate = Storage::SharedMediaSliceUpdate;
		Auth().storage().sharedMediaSliceUpdated(
		) | rpl::filter([=](const SliceUpdate &update) {
			return (update.peerId == key.peerId)
				&& (update.type == key.type);
		}) | rpl::filter([=](const SliceUpdate &update) {
			return builder->applyUpdate(update.data);
		}) | rpl::start_with_next(pushNextSnapshot, lifetime);

		using OneRemoved = Storage::SharedMediaRemoveOne;
		Auth().storage().sharedMediaOneRemoved(
		) | rpl::filter([=](const OneRemoved &update) {
			return (update.peerId == key.peerId)
				&& update.types.test(key.type);
		}) | rpl::filter([=](const OneRemoved &update) {
			return builder->removeOne(update.messageId);
		}) | rpl::start_with_next(pushNextSnapshot, lifetime);

		using AllRemoved = Storage::SharedMediaRemoveAll;
		Auth().storage().sharedMediaAllRemoved(
		) | rpl::filter([=](const AllRemoved &update) {
			return (update.peerId == key.peerId);
		}) | rpl::filter([=] {
			return builder->removeAll();
		}) | rpl::start_with_next(pushNextSnapshot, lifetime);

		using InvalidateBottom = Storage::SharedMediaInvalidateBottom;
		Auth().storage().sharedMediaBottomInvalidated(
		) | rpl::filter([=](const InvalidateBottom &update) {
			return (update.peerId == key.peerId);
		}) | rpl::filter([=] {
			return builder->invalidateBottom();
		}) | rpl::start_with_next(pushNextSnapshot, lifetime);

		using Result = Storage::SharedMediaResult;
		Auth().storage().query(Storage::SharedMediaQuery(
			key,
			limitBefore,
			limitAfter
		)) | rpl::filter([=](const Result &result) {
			return builder->applyInitial(result);
		}) | rpl::start_with_next_done(
			pushNextSnapshot,
			[=] { builder->checkInsufficient(); },
			lifetime);

		return lifetime;
	};
}
rpl::producer<SparseIdsSlice> SearchController::simpleIdsSlice(
		PeerId peerId,
		MsgId aroundId,
		const Query &query,
		int limitBefore,
		int limitAfter) {
	Expects(peerId != 0);
	Expects(IsServerMsgId(aroundId) || (aroundId == 0));
	Expects((aroundId != 0)
		|| (limitBefore == 0 && limitAfter == 0));
	Expects((query.peerId == peerId)
		|| (query.migratedPeerId == peerId));

	auto it = _cache.find(query);
	if (it == _cache.end()) {
		return [=](auto) { return rpl::lifetime(); };
	}

	auto listData = (peerId == query.peerId)
		? &it->second->peerData
		: &*it->second->migratedData;
	return [=](auto consumer) {
		auto lifetime = rpl::lifetime();
		auto builder = lifetime.make_state<SparseIdsSliceBuilder>(
			aroundId,
			limitBefore,
			limitAfter);
		builder->insufficientAround(
		) | rpl::start_with_next([=](
				const SparseIdsSliceBuilder::AroundData &data) {
			requestMore(data, query, listData);
		}, lifetime);

		auto pushNextSnapshot = [=] {
			consumer.put_next(builder->snapshot());
		};

		listData->list.sliceUpdated(
		) | rpl::filter([=](const SliceUpdate &update) {
			return builder->applyUpdate(update);
		}) | rpl::start_with_next(pushNextSnapshot, lifetime);

		Auth().data().itemRemoved(
		) | rpl::filter([=](not_null<const HistoryItem*> item) {
			return (item->history()->peer->id == peerId);
		}) | rpl::filter([=](not_null<const HistoryItem*> item) {
			return builder->removeOne(item->id);
		}) | rpl::start_with_next(pushNextSnapshot, lifetime);

		Auth().data().historyCleared(
		) | rpl::filter([=](not_null<const History*> history) {
			return (history->peer->id == peerId);
		}) | rpl::filter([=] {
			return builder->removeAll();
		}) | rpl::start_with_next(pushNextSnapshot, lifetime);

		using Result = Storage::SparseIdsListResult;
		listData->list.query(Storage::SparseIdsListQuery(
			aroundId,
			limitBefore,
			limitAfter
		)) | rpl::filter([=](const Result &result) {
			return builder->applyInitial(result);
		}) | rpl::start_with_next_done(
			pushNextSnapshot,
			[=] { builder->checkInsufficient(); },
			lifetime);

		return lifetime;
	};
}
Ejemplo n.º 4
0
bool MessagesSliceBuilder::bottomInvalidated() {
	_fullCount = _skippedAfter = std::nullopt;
	checkInsufficient();
	return true;
}
Ejemplo n.º 5
0
bool MessagesSliceBuilder::invalidated() {
	_fullCount = _skippedBefore = _skippedAfter = std::nullopt;
	_ids.clear();
	checkInsufficient();
	return false;
}