Remove notifications support.
GitOrigin-RevId: 89669ed19bba2d9556005422d003dec7df8cf252
This commit is contained in:
parent
383119ebe6
commit
7ac17547be
@ -172,6 +172,8 @@ void NotificationManager::add_notification(NotificationGroupId group_id, DialogI
|
||||
group_key.dialog_id = dialog_id;
|
||||
group_key.last_notification_date = 0;
|
||||
group_it = std::move(groups_.emplace(group_key, NotificationGroup()).first);
|
||||
|
||||
// TODO synchronously load old group notifications from the database
|
||||
}
|
||||
|
||||
PendingNotification notification;
|
||||
@ -235,7 +237,8 @@ void NotificationManager::flush_pending_notifications(NotificationGroupKey &grou
|
||||
vector<td_api::object_ptr<td_api::notification>> added_notifications;
|
||||
added_notifications.reserve(pending_notifications.size());
|
||||
for (auto &pending_notification : pending_notifications) {
|
||||
Notification notification{pending_notification.notification_id, std::move(pending_notification.type)};
|
||||
Notification notification{pending_notification.notification_id, pending_notification.date,
|
||||
std::move(pending_notification.type)};
|
||||
added_notifications.push_back(get_notification_object(group_key.dialog_id, notification));
|
||||
if (added_notifications.back()->type_ == nullptr) {
|
||||
added_notifications.pop_back();
|
||||
@ -314,12 +317,16 @@ void NotificationManager::send_add_group_update(const NotificationGroupKey &grou
|
||||
void NotificationManager::flush_pending_notifications(NotificationGroupId group_id) {
|
||||
auto group_it = get_group(group_id);
|
||||
CHECK(group_it != groups_.end());
|
||||
|
||||
if (group_it->second.pending_notifications.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto group_key = group_it->first;
|
||||
auto group = std::move(group_it->second);
|
||||
|
||||
groups_.erase(group_it);
|
||||
|
||||
CHECK(!group.pending_notifications.empty());
|
||||
auto final_group_key = group_key;
|
||||
for (auto &pending_notification : group.pending_notifications) {
|
||||
if (pending_notification.date >= final_group_key.last_notification_date) {
|
||||
@ -340,7 +347,8 @@ void NotificationManager::flush_pending_notifications(NotificationGroupId group_
|
||||
VLOG(notifications) << "There is no need to send updateNotificationGroup in " << group_key
|
||||
<< ", because of newer notification groups";
|
||||
for (auto &pending_notification : group.pending_notifications) {
|
||||
group.notifications.emplace_back(pending_notification.notification_id, std::move(pending_notification.type));
|
||||
group.notifications.emplace_back(pending_notification.notification_id, pending_notification.date,
|
||||
std::move(pending_notification.type));
|
||||
}
|
||||
} else {
|
||||
if (!was_updated) {
|
||||
@ -410,8 +418,72 @@ void NotificationManager::edit_notification(NotificationGroupId group_id, Notifi
|
||||
}
|
||||
}
|
||||
|
||||
void NotificationManager::on_notifications_removed(
|
||||
NotificationGroups::iterator &&group_it, vector<td_api::object_ptr<td_api::notification>> &&added_notifications,
|
||||
vector<int32> &&removed_notification_ids) {
|
||||
auto group_key = group_it->first;
|
||||
auto final_group_key = group_key;
|
||||
final_group_key.last_notification_date = 0;
|
||||
for (auto ¬ification : group_it->second.notifications) {
|
||||
if (notification.date > final_group_key.last_notification_date) {
|
||||
final_group_key.last_notification_date = notification.date;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_position_changed = final_group_key.last_notification_date != group_key.last_notification_date;
|
||||
|
||||
NotificationGroup group = std::move(group_it->second);
|
||||
if (is_position_changed) {
|
||||
VLOG(notifications) << "Position of notification group is changed from " << group_key << " to " << final_group_key;
|
||||
groups_.erase(group_it);
|
||||
}
|
||||
|
||||
auto last_group_key = get_last_updated_group_key();
|
||||
bool was_updated = false;
|
||||
bool is_updated = false;
|
||||
if (is_position_changed) {
|
||||
was_updated = group_key.last_notification_date != 0 && group_key < last_group_key;
|
||||
is_updated = final_group_key.last_notification_date != 0 && final_group_key < last_group_key;
|
||||
} else {
|
||||
was_updated = is_updated = !(last_group_key < group_key);
|
||||
}
|
||||
|
||||
if (!was_updated) {
|
||||
CHECK(!is_updated);
|
||||
// there is no need to send update
|
||||
} else {
|
||||
if (is_updated) {
|
||||
// group is still visible
|
||||
send_update_notification_group(td_api::make_object<td_api::updateNotificationGroup>(
|
||||
group_key.group_id.get(), group_key.dialog_id.get(), 0, true, group.total_count,
|
||||
std::move(added_notifications), std::move(removed_notification_ids)));
|
||||
} else {
|
||||
// group needs to be removed
|
||||
send_remove_group_update(group_key.group_id);
|
||||
if (last_group_key.last_notification_date != 0) {
|
||||
// need to add new last notification group
|
||||
send_add_group_update(last_group_key, groups_[last_group_key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_position_changed) {
|
||||
groups_.emplace(std::move(final_group_key), std::move(group));
|
||||
|
||||
last_group_key = get_last_updated_group_key();
|
||||
} else {
|
||||
group_it->second = std::move(group);
|
||||
}
|
||||
|
||||
/*
|
||||
if (last_loaded_group_key_ < last_group_key) {
|
||||
// TODO load new groups from database
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void NotificationManager::remove_notification(NotificationGroupId group_id, NotificationId notification_id,
|
||||
Promise<Unit> &&promise) {
|
||||
bool is_permanent, Promise<Unit> &&promise) {
|
||||
if (!notification_id.is_valid()) {
|
||||
return promise.set_error(Status::Error(400, "Notification identifier is invalid"));
|
||||
}
|
||||
@ -420,16 +492,67 @@ void NotificationManager::remove_notification(NotificationGroupId group_id, Noti
|
||||
return promise.set_value(Unit());
|
||||
}
|
||||
|
||||
VLOG(notifications) << "Remove " << notification_id;
|
||||
VLOG(notifications) << "Remove " << notification_id << " from " << group_id;
|
||||
|
||||
// TODO remove notification from database by notification_id
|
||||
|
||||
// TODO update total_count
|
||||
auto group_it = get_group(group_id);
|
||||
if (group_it == groups_.end()) {
|
||||
// TODO synchronously load the group
|
||||
return promise.set_value(Unit());
|
||||
}
|
||||
|
||||
for (auto it = group_it->second.pending_notifications.begin(); it != group_it->second.pending_notifications.end();
|
||||
++it) {
|
||||
if (it->notification_id == notification_id) {
|
||||
// notification is still pending, just delete it
|
||||
group_it->second.pending_notifications.erase(it);
|
||||
if (group_it->second.pending_notifications.empty()) {
|
||||
flush_pending_notifications_timeout_.cancel_timeout(group_id.get());
|
||||
}
|
||||
return promise.set_value(Unit());
|
||||
}
|
||||
}
|
||||
|
||||
bool is_found = false;
|
||||
auto old_group_size = group_it->second.notifications.size();
|
||||
size_t notification_pos = old_group_size;
|
||||
for (size_t pos = 0; pos < notification_pos; pos++) {
|
||||
if (group_it->second.notifications[pos].notification_id == notification_id) {
|
||||
notification_pos = pos;
|
||||
is_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
vector<td_api::object_ptr<td_api::notification>> added_notifications;
|
||||
vector<int32> removed_notification_ids;
|
||||
if (is_found && notification_pos + max_notification_group_size_ >= old_group_size) {
|
||||
removed_notification_ids.push_back(notification_id.get());
|
||||
if (old_group_size >= max_notification_group_size_ + 1) {
|
||||
added_notifications.push_back(
|
||||
get_notification_object(group_it->first.dialog_id,
|
||||
group_it->second.notifications[old_group_size - max_notification_group_size_ - 1]));
|
||||
} else {
|
||||
// TODO preload more notifications in the group
|
||||
}
|
||||
}
|
||||
|
||||
if (is_permanent) {
|
||||
group_it->second.total_count--;
|
||||
}
|
||||
if (is_found) {
|
||||
group_it->second.notifications.erase(group_it->second.notifications.begin() + notification_pos);
|
||||
}
|
||||
|
||||
if (is_permanent || !removed_notification_ids.empty()) {
|
||||
on_notifications_removed(std::move(group_it), std::move(added_notifications), std::move(removed_notification_ids));
|
||||
}
|
||||
|
||||
promise.set_value(Unit());
|
||||
}
|
||||
|
||||
void NotificationManager::remove_notification_group(NotificationGroupId group_id, NotificationId max_notification_id,
|
||||
Promise<Unit> &&promise) {
|
||||
int32 new_total_count, Promise<Unit> &&promise) {
|
||||
if (!group_id.is_valid()) {
|
||||
return promise.set_error(Status::Error(400, "Group identifier is invalid"));
|
||||
}
|
||||
@ -443,7 +566,62 @@ void NotificationManager::remove_notification_group(NotificationGroupId group_id
|
||||
|
||||
VLOG(notifications) << "Remove " << group_id << " up to " << max_notification_id;
|
||||
|
||||
// TODO update total_count
|
||||
// TODO remove notifications from database by max_notification_id, save that they are removed
|
||||
|
||||
auto group_it = get_group(group_id);
|
||||
if (group_it == groups_.end()) {
|
||||
// TODO synchronously load the group
|
||||
return promise.set_value(Unit());
|
||||
}
|
||||
|
||||
auto pending_delete_end = group_it->second.pending_notifications.begin();
|
||||
for (auto it = group_it->second.pending_notifications.begin(); it != group_it->second.pending_notifications.end();
|
||||
++it) {
|
||||
if (it->notification_id.get() <= max_notification_id.get()) {
|
||||
pending_delete_end = it + 1;
|
||||
}
|
||||
}
|
||||
group_it->second.pending_notifications.erase(group_it->second.pending_notifications.begin(), pending_delete_end);
|
||||
if (group_it->second.pending_notifications.empty()) {
|
||||
flush_pending_notifications_timeout_.cancel_timeout(group_id.get());
|
||||
}
|
||||
if (new_total_count != -1) {
|
||||
new_total_count -= static_cast<int32>(group_it->second.pending_notifications.size());
|
||||
if (new_total_count < 0) {
|
||||
LOG(ERROR) << "Have wrong new_total_count " << new_total_count;
|
||||
}
|
||||
}
|
||||
|
||||
auto old_group_size = group_it->second.notifications.size();
|
||||
auto notification_delete_end = old_group_size;
|
||||
for (size_t pos = 0; pos < notification_delete_end; pos++) {
|
||||
if (group_it->second.notifications[pos].notification_id.get() > max_notification_id.get()) {
|
||||
notification_delete_end = pos;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_found = notification_delete_end != 0;
|
||||
|
||||
vector<int32> removed_notification_ids;
|
||||
if (is_found && notification_delete_end + max_notification_group_size_ > old_group_size) {
|
||||
for (size_t i = old_group_size; i < notification_delete_end + max_notification_group_size_; i++) {
|
||||
removed_notification_ids.push_back(
|
||||
group_it->second.notifications[i - max_notification_group_size_].notification_id.get());
|
||||
}
|
||||
}
|
||||
|
||||
if (new_total_count != -1) {
|
||||
group_it->second.total_count = new_total_count;
|
||||
}
|
||||
if (is_found) {
|
||||
group_it->second.notifications.erase(group_it->second.notifications.begin(),
|
||||
group_it->second.notifications.begin() + notification_delete_end);
|
||||
}
|
||||
|
||||
if (new_total_count != -1 || !removed_notification_ids.empty()) {
|
||||
on_notifications_removed(std::move(group_it), vector<td_api::object_ptr<td_api::notification>>(),
|
||||
std::move(removed_notification_ids));
|
||||
}
|
||||
promise.set_value(Unit());
|
||||
}
|
||||
|
||||
|
@ -49,10 +49,11 @@ class NotificationManager : public Actor {
|
||||
void edit_notification(NotificationGroupId group_id, NotificationId notification_id,
|
||||
unique_ptr<NotificationType> type);
|
||||
|
||||
void remove_notification(NotificationGroupId group_id, NotificationId notification_id, Promise<Unit> &&promise);
|
||||
void remove_notification(NotificationGroupId group_id, NotificationId notification_id, bool is_permanent,
|
||||
Promise<Unit> &&promise);
|
||||
|
||||
void remove_notification_group(NotificationGroupId group_id, NotificationId max_notification_id,
|
||||
Promise<Unit> &&promise);
|
||||
int32 new_total_count, Promise<Unit> &&promise);
|
||||
|
||||
void on_notification_group_count_max_changed();
|
||||
|
||||
@ -77,10 +78,11 @@ class NotificationManager : public Actor {
|
||||
|
||||
struct Notification {
|
||||
NotificationId notification_id;
|
||||
int32 date = 0;
|
||||
unique_ptr<NotificationType> type;
|
||||
|
||||
Notification(NotificationId notification_id, unique_ptr<NotificationType> type)
|
||||
: notification_id(notification_id), type(std::move(type)) {
|
||||
Notification(NotificationId notification_id, int32 date, unique_ptr<NotificationType> type)
|
||||
: notification_id(notification_id), date(date), type(std::move(type)) {
|
||||
}
|
||||
};
|
||||
|
||||
@ -153,6 +155,10 @@ class NotificationManager : public Actor {
|
||||
|
||||
void flush_pending_notifications(NotificationGroupId group_id);
|
||||
|
||||
void on_notifications_removed(NotificationGroups::iterator &&group_it,
|
||||
vector<td_api::object_ptr<td_api::notification>> &&added_notifications,
|
||||
vector<int32> &&removed_notification_ids);
|
||||
|
||||
NotificationId current_notification_id_;
|
||||
NotificationGroupId current_notification_group_id_;
|
||||
|
||||
|
@ -5086,14 +5086,15 @@ void Td::on_request(uint64 id, const td_api::removeNotification &request) {
|
||||
CHECK_IS_USER();
|
||||
CREATE_OK_REQUEST_PROMISE();
|
||||
notification_manager_->remove_notification(NotificationGroupId(request.notification_group_id_),
|
||||
NotificationId(request.notification_id_), std::move(promise));
|
||||
NotificationId(request.notification_id_), false, std::move(promise));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, const td_api::removeNotificationGroup &request) {
|
||||
CHECK_IS_USER();
|
||||
CREATE_OK_REQUEST_PROMISE();
|
||||
notification_manager_->remove_notification_group(NotificationGroupId(request.notification_group_id_),
|
||||
NotificationId(request.max_notification_id_), std::move(promise));
|
||||
NotificationId(request.max_notification_id_), -1,
|
||||
std::move(promise));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, const td_api::deleteMessages &request) {
|
||||
|
Reference in New Issue
Block a user