2017-09-04 11:40:02 +00:00
|
|
|
/*
|
|
|
|
This file is part of Telegram Desktop,
|
2018-01-03 10:23:14 +00:00
|
|
|
the official desktop application for the Telegram messaging service.
|
2017-09-04 11:40:02 +00:00
|
|
|
|
2018-01-03 10:23:14 +00:00
|
|
|
For license and copyright information please follow this link:
|
|
|
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
2017-09-04 11:40:02 +00:00
|
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
|
2017-09-13 16:57:44 +00:00
|
|
|
#include <rpl/event_stream.h>
|
2017-09-04 11:40:02 +00:00
|
|
|
#include "storage/storage_facade.h"
|
2017-10-29 15:32:01 +00:00
|
|
|
#include "storage/storage_sparse_ids_list.h"
|
2017-09-04 11:40:02 +00:00
|
|
|
|
|
|
|
namespace Storage {
|
|
|
|
|
|
|
|
// Allow forward declarations.
|
2018-03-09 20:48:47 +00:00
|
|
|
enum class SharedMediaType : signed char {
|
2017-12-28 10:11:50 +00:00
|
|
|
Photo,
|
|
|
|
Video,
|
|
|
|
PhotoVideo,
|
|
|
|
MusicFile,
|
|
|
|
File,
|
|
|
|
VoiceFile,
|
|
|
|
Link,
|
|
|
|
ChatPhoto,
|
|
|
|
RoundVoiceFile,
|
|
|
|
GIF,
|
|
|
|
RoundFile,
|
2020-10-20 16:29:24 +00:00
|
|
|
Pinned,
|
2017-09-04 11:40:02 +00:00
|
|
|
|
2017-12-28 10:11:50 +00:00
|
|
|
kCount,
|
2017-09-04 11:40:02 +00:00
|
|
|
};
|
|
|
|
constexpr auto kSharedMediaTypeCount = static_cast<int>(SharedMediaType::kCount);
|
|
|
|
constexpr bool IsValidSharedMediaType(SharedMediaType type) {
|
|
|
|
return (static_cast<int>(type) >= 0)
|
|
|
|
&& (static_cast<int>(type) < kSharedMediaTypeCount);
|
|
|
|
}
|
|
|
|
|
|
|
|
using SharedMediaTypesMask = base::enum_mask<SharedMediaType>;
|
|
|
|
|
|
|
|
struct SharedMediaAddNew {
|
2022-10-11 15:08:19 +00:00
|
|
|
SharedMediaAddNew(
|
|
|
|
PeerId peerId,
|
|
|
|
SharedMediaTypesMask types,
|
|
|
|
MsgId messageId)
|
|
|
|
: peerId(peerId)
|
|
|
|
, messageId(messageId)
|
|
|
|
, types(types) {
|
2017-09-04 11:40:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PeerId peerId = 0;
|
|
|
|
MsgId messageId = 0;
|
|
|
|
SharedMediaTypesMask types;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
struct SharedMediaAddExisting {
|
|
|
|
SharedMediaAddExisting(
|
|
|
|
PeerId peerId,
|
2022-10-11 15:08:19 +00:00
|
|
|
MsgId topicRootId,
|
2017-09-04 11:40:02 +00:00
|
|
|
SharedMediaTypesMask types,
|
|
|
|
MsgId messageId,
|
|
|
|
MsgRange noSkipRange)
|
2022-10-11 15:08:19 +00:00
|
|
|
: peerId(peerId)
|
|
|
|
, topicRootId(topicRootId)
|
|
|
|
, messageId(messageId)
|
|
|
|
, noSkipRange(noSkipRange)
|
|
|
|
, types(types) {
|
2017-09-04 11:40:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PeerId peerId = 0;
|
2022-10-11 15:08:19 +00:00
|
|
|
MsgId topicRootId = 0;
|
2017-09-04 11:40:02 +00:00
|
|
|
MsgId messageId = 0;
|
|
|
|
MsgRange noSkipRange;
|
|
|
|
SharedMediaTypesMask types;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
struct SharedMediaAddSlice {
|
|
|
|
SharedMediaAddSlice(
|
|
|
|
PeerId peerId,
|
2022-10-11 15:08:19 +00:00
|
|
|
MsgId topicRootId,
|
2017-09-04 11:40:02 +00:00
|
|
|
SharedMediaType type,
|
|
|
|
std::vector<MsgId> &&messageIds,
|
|
|
|
MsgRange noSkipRange,
|
2018-09-21 16:28:46 +00:00
|
|
|
std::optional<int> count = std::nullopt)
|
2022-10-11 15:08:19 +00:00
|
|
|
: peerId(peerId)
|
|
|
|
, topicRootId(topicRootId)
|
|
|
|
, messageIds(std::move(messageIds))
|
|
|
|
, noSkipRange(noSkipRange)
|
|
|
|
, type(type)
|
|
|
|
, count(count) {
|
2017-09-04 11:40:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PeerId peerId = 0;
|
2022-10-11 15:08:19 +00:00
|
|
|
MsgId topicRootId = 0;
|
2017-09-04 11:40:02 +00:00
|
|
|
std::vector<MsgId> messageIds;
|
|
|
|
MsgRange noSkipRange;
|
|
|
|
SharedMediaType type = SharedMediaType::kCount;
|
2018-09-21 16:28:46 +00:00
|
|
|
std::optional<int> count;
|
2017-09-04 11:40:02 +00:00
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
struct SharedMediaRemoveOne {
|
|
|
|
SharedMediaRemoveOne(
|
|
|
|
PeerId peerId,
|
|
|
|
SharedMediaTypesMask types,
|
|
|
|
MsgId messageId)
|
2017-10-29 15:32:01 +00:00
|
|
|
: peerId(peerId)
|
|
|
|
, messageId(messageId)
|
|
|
|
, types(types) {
|
2017-09-04 11:40:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PeerId peerId = 0;
|
|
|
|
MsgId messageId = 0;
|
|
|
|
SharedMediaTypesMask types;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
struct SharedMediaRemoveAll {
|
2020-10-20 16:29:24 +00:00
|
|
|
SharedMediaRemoveAll(
|
|
|
|
PeerId peerId,
|
|
|
|
SharedMediaTypesMask types = SharedMediaTypesMask::All())
|
|
|
|
: peerId(peerId)
|
|
|
|
, types(types) {
|
2017-09-04 11:40:02 +00:00
|
|
|
}
|
2022-11-01 05:22:21 +00:00
|
|
|
SharedMediaRemoveAll(
|
|
|
|
PeerId peerId,
|
|
|
|
MsgId topicRootId,
|
|
|
|
SharedMediaTypesMask types = SharedMediaTypesMask::All())
|
|
|
|
: peerId(peerId)
|
|
|
|
, topicRootId(topicRootId)
|
|
|
|
, types(types) {
|
|
|
|
}
|
2017-09-04 11:40:02 +00:00
|
|
|
|
|
|
|
PeerId peerId = 0;
|
2022-11-01 05:22:21 +00:00
|
|
|
MsgId topicRootId = 0;
|
2020-10-20 16:29:24 +00:00
|
|
|
SharedMediaTypesMask types;
|
2017-09-04 11:40:02 +00:00
|
|
|
|
|
|
|
};
|
|
|
|
|
2018-02-05 14:37:22 +00:00
|
|
|
struct SharedMediaInvalidateBottom {
|
|
|
|
SharedMediaInvalidateBottom(PeerId peerId) : peerId(peerId) {
|
|
|
|
}
|
|
|
|
|
|
|
|
PeerId peerId = 0;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2017-08-18 19:14:31 +00:00
|
|
|
struct SharedMediaKey {
|
|
|
|
SharedMediaKey(
|
2017-09-04 11:40:02 +00:00
|
|
|
PeerId peerId,
|
2022-10-11 15:08:19 +00:00
|
|
|
MsgId topicRootId,
|
2017-09-04 11:40:02 +00:00
|
|
|
SharedMediaType type,
|
2017-08-18 19:14:31 +00:00
|
|
|
MsgId messageId)
|
2017-10-29 15:32:01 +00:00
|
|
|
: peerId(peerId)
|
2022-10-11 15:08:19 +00:00
|
|
|
, topicRootId(topicRootId)
|
2017-10-29 15:32:01 +00:00
|
|
|
, type(type)
|
|
|
|
, messageId(messageId) {
|
2017-08-18 19:14:31 +00:00
|
|
|
}
|
|
|
|
|
2022-10-11 15:08:19 +00:00
|
|
|
friend inline constexpr auto operator<=>(
|
|
|
|
const SharedMediaKey &,
|
|
|
|
const SharedMediaKey &) = default;
|
2017-09-04 11:40:02 +00:00
|
|
|
|
|
|
|
PeerId peerId = 0;
|
2022-10-11 15:08:19 +00:00
|
|
|
MsgId topicRootId = 0;
|
2017-08-18 19:14:31 +00:00
|
|
|
SharedMediaType type = SharedMediaType::kCount;
|
2017-09-04 11:40:02 +00:00
|
|
|
MsgId messageId = 0;
|
2017-08-18 19:14:31 +00:00
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
struct SharedMediaQuery {
|
|
|
|
SharedMediaQuery(
|
|
|
|
SharedMediaKey key,
|
|
|
|
int limitBefore,
|
|
|
|
int limitAfter)
|
2017-10-29 15:32:01 +00:00
|
|
|
: key(key)
|
|
|
|
, limitBefore(limitBefore)
|
|
|
|
, limitAfter(limitAfter) {
|
2017-08-18 19:14:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SharedMediaKey key;
|
2017-09-04 11:40:02 +00:00
|
|
|
int limitBefore = 0;
|
|
|
|
int limitAfter = 0;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2017-10-29 15:32:01 +00:00
|
|
|
using SharedMediaResult = SparseIdsListResult;
|
2017-09-04 11:40:02 +00:00
|
|
|
|
2017-08-18 19:14:31 +00:00
|
|
|
struct SharedMediaSliceUpdate {
|
|
|
|
SharedMediaSliceUpdate(
|
|
|
|
PeerId peerId,
|
2022-10-11 15:08:19 +00:00
|
|
|
MsgId topicRootId,
|
2017-08-18 19:14:31 +00:00
|
|
|
SharedMediaType type,
|
2017-10-29 15:32:01 +00:00
|
|
|
const SparseIdsSliceUpdate &data)
|
|
|
|
: peerId(peerId)
|
2022-10-11 15:08:19 +00:00
|
|
|
, topicRootId(topicRootId)
|
2017-10-29 15:32:01 +00:00
|
|
|
, type(type)
|
|
|
|
, data(data) {
|
2017-08-18 19:14:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PeerId peerId = 0;
|
2022-10-11 15:08:19 +00:00
|
|
|
MsgId topicRootId = 0;
|
2017-08-18 19:14:31 +00:00
|
|
|
SharedMediaType type = SharedMediaType::kCount;
|
2017-10-29 15:32:01 +00:00
|
|
|
SparseIdsSliceUpdate data;
|
2017-08-18 19:14:31 +00:00
|
|
|
};
|
|
|
|
|
2022-10-28 05:19:27 +00:00
|
|
|
struct SharedMediaUnloadThread {
|
|
|
|
SharedMediaUnloadThread(
|
|
|
|
PeerId peerId,
|
|
|
|
MsgId topicRootId)
|
|
|
|
: peerId(peerId)
|
|
|
|
, topicRootId(topicRootId) {
|
|
|
|
}
|
|
|
|
|
|
|
|
PeerId peerId = 0;
|
|
|
|
MsgId topicRootId = 0;
|
|
|
|
};
|
|
|
|
|
2017-09-04 19:14:44 +00:00
|
|
|
class SharedMedia {
|
2017-09-04 11:40:02 +00:00
|
|
|
public:
|
|
|
|
using Type = SharedMediaType;
|
|
|
|
|
|
|
|
void add(SharedMediaAddNew &&query);
|
|
|
|
void add(SharedMediaAddExisting &&query);
|
|
|
|
void add(SharedMediaAddSlice &&query);
|
|
|
|
void remove(SharedMediaRemoveOne &&query);
|
|
|
|
void remove(SharedMediaRemoveAll &&query);
|
2018-02-05 14:37:22 +00:00
|
|
|
void invalidate(SharedMediaInvalidateBottom &&query);
|
2022-10-28 05:19:27 +00:00
|
|
|
void unload(SharedMediaUnloadThread &&query);
|
2017-09-04 11:40:02 +00:00
|
|
|
|
2017-09-04 19:14:44 +00:00
|
|
|
rpl::producer<SharedMediaResult> query(SharedMediaQuery &&query) const;
|
2020-10-20 16:29:24 +00:00
|
|
|
SharedMediaResult snapshot(const SharedMediaQuery &query) const;
|
|
|
|
bool empty(const SharedMediaKey &key) const;
|
2017-11-21 09:20:56 +00:00
|
|
|
rpl::producer<SharedMediaSliceUpdate> sliceUpdated() const;
|
|
|
|
rpl::producer<SharedMediaRemoveOne> oneRemoved() const;
|
|
|
|
rpl::producer<SharedMediaRemoveAll> allRemoved() const;
|
2018-02-05 14:37:22 +00:00
|
|
|
rpl::producer<SharedMediaInvalidateBottom> bottomInvalidated() const;
|
2017-08-18 19:14:31 +00:00
|
|
|
|
2017-09-04 11:40:02 +00:00
|
|
|
private:
|
2022-10-11 15:08:19 +00:00
|
|
|
struct Key {
|
|
|
|
PeerId peerId = 0;
|
|
|
|
MsgId topicRootId = 0;
|
|
|
|
|
|
|
|
friend inline constexpr auto operator<=>(Key, Key) = default;
|
|
|
|
};
|
2017-10-29 15:32:01 +00:00
|
|
|
using Lists = std::array<SparseIdsList, kSharedMediaTypeCount>;
|
2017-09-04 11:40:02 +00:00
|
|
|
|
2022-10-11 15:08:19 +00:00
|
|
|
std::map<Key, Lists>::iterator enforceLists(Key key);
|
2017-08-18 19:14:31 +00:00
|
|
|
|
2022-10-11 15:08:19 +00:00
|
|
|
std::map<Key, Lists> _lists;
|
2017-09-04 11:40:02 +00:00
|
|
|
|
2017-09-04 19:14:44 +00:00
|
|
|
rpl::event_stream<SharedMediaSliceUpdate> _sliceUpdated;
|
|
|
|
rpl::event_stream<SharedMediaRemoveOne> _oneRemoved;
|
|
|
|
rpl::event_stream<SharedMediaRemoveAll> _allRemoved;
|
2018-02-05 14:37:22 +00:00
|
|
|
rpl::event_stream<SharedMediaInvalidateBottom> _bottomInvalidated;
|
2017-09-04 19:14:44 +00:00
|
|
|
|
2017-09-30 18:26:45 +00:00
|
|
|
rpl::lifetime _lifetime;
|
|
|
|
|
2017-09-04 11:40:02 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace Storage
|