2021-10-13 16:08:35 -04:00
|
|
|
#include "components/ble/NotificationManager.h"
|
2020-03-28 14:05:28 -04:00
|
|
|
#include <cstring>
|
2020-10-20 14:57:39 -04:00
|
|
|
#include <algorithm>
|
2022-05-19 13:59:09 -04:00
|
|
|
#include <cassert>
|
2020-03-28 14:05:28 -04:00
|
|
|
|
|
|
|
using namespace Pinetime::Controllers;
|
|
|
|
|
2020-10-21 11:31:56 -04:00
|
|
|
constexpr uint8_t NotificationManager::MessageSize;
|
|
|
|
|
2021-04-18 13:28:14 -04:00
|
|
|
void NotificationManager::Push(NotificationManager::Notification&& notif) {
|
2020-10-20 14:57:39 -04:00
|
|
|
notif.id = GetNextId();
|
|
|
|
notif.valid = true;
|
|
|
|
newNotification = true;
|
2022-05-19 13:59:09 -04:00
|
|
|
if (beginIdx > 0) {
|
|
|
|
--beginIdx;
|
|
|
|
} else {
|
|
|
|
beginIdx = notifications.size() - 1;
|
|
|
|
}
|
|
|
|
notifications[beginIdx] = std::move(notif);
|
|
|
|
if (size < notifications.size()) {
|
|
|
|
size++;
|
|
|
|
}
|
2020-10-20 14:57:39 -04:00
|
|
|
}
|
2020-03-28 14:05:28 -04:00
|
|
|
|
2020-10-20 14:57:39 -04:00
|
|
|
NotificationManager::Notification::Id NotificationManager::GetNextId() {
|
|
|
|
return nextId++;
|
|
|
|
}
|
2020-03-28 14:05:28 -04:00
|
|
|
|
2022-05-19 13:59:09 -04:00
|
|
|
NotificationManager::Notification NotificationManager::GetLastNotification() const {
|
|
|
|
if (this->IsEmpty()) {
|
2021-04-18 13:28:14 -04:00
|
|
|
return {};
|
2022-05-19 13:59:09 -04:00
|
|
|
}
|
|
|
|
return this->At(0);
|
|
|
|
}
|
2020-10-20 14:57:39 -04:00
|
|
|
|
2022-05-19 13:59:09 -04:00
|
|
|
const NotificationManager::Notification& NotificationManager::At(NotificationManager::Notification::Idx idx) const {
|
|
|
|
if (idx >= notifications.size()) {
|
|
|
|
assert(false);
|
|
|
|
return notifications.at(beginIdx); // this should not happen
|
|
|
|
}
|
|
|
|
size_t read_idx = (beginIdx + idx) % notifications.size();
|
|
|
|
return notifications.at(read_idx);
|
2020-03-28 14:05:28 -04:00
|
|
|
}
|
2020-10-20 14:57:39 -04:00
|
|
|
|
2022-05-19 13:59:09 -04:00
|
|
|
NotificationManager::Notification& NotificationManager::At(NotificationManager::Notification::Idx idx) {
|
|
|
|
if (idx >= notifications.size()) {
|
|
|
|
assert(false);
|
|
|
|
return notifications.at(beginIdx); // this should not happen
|
|
|
|
}
|
|
|
|
size_t read_idx = (beginIdx + idx) % notifications.size();
|
|
|
|
return notifications.at(read_idx);
|
|
|
|
}
|
2020-10-20 14:57:39 -04:00
|
|
|
|
2022-05-19 13:59:09 -04:00
|
|
|
NotificationManager::Notification::Idx NotificationManager::IndexOf(NotificationManager::Notification::Id id) const {
|
|
|
|
for (NotificationManager::Notification::Idx idx = 0; idx < this->size; idx++) {
|
|
|
|
const NotificationManager::Notification& notification = this->At(idx);
|
|
|
|
if (notification.id == id) {
|
|
|
|
return idx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return size;
|
|
|
|
}
|
2020-10-20 14:57:39 -04:00
|
|
|
|
2022-05-19 13:59:09 -04:00
|
|
|
NotificationManager::Notification NotificationManager::Get(NotificationManager::Notification::Id id) const {
|
|
|
|
NotificationManager::Notification::Idx idx = this->IndexOf(id);
|
|
|
|
if (idx == this->size) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
return this->At(idx);
|
|
|
|
}
|
2020-10-20 14:57:39 -04:00
|
|
|
|
2022-05-19 13:59:09 -04:00
|
|
|
NotificationManager::Notification NotificationManager::GetNext(NotificationManager::Notification::Id id) const {
|
|
|
|
NotificationManager::Notification::Idx idx = this->IndexOf(id);
|
|
|
|
if (idx == this->size) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
if (idx == 0 || idx > notifications.size()) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
return this->At(idx - 1);
|
|
|
|
}
|
2020-10-20 14:57:39 -04:00
|
|
|
|
2022-05-19 13:59:09 -04:00
|
|
|
NotificationManager::Notification NotificationManager::GetPrevious(NotificationManager::Notification::Id id) const {
|
|
|
|
NotificationManager::Notification::Idx idx = this->IndexOf(id);
|
|
|
|
if (idx == this->size) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
if (static_cast<size_t>(idx + 1) >= notifications.size()) {
|
2021-04-18 13:28:14 -04:00
|
|
|
return {};
|
2022-05-19 13:59:09 -04:00
|
|
|
}
|
|
|
|
return this->At(idx + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void NotificationManager::DismissIdx(NotificationManager::Notification::Idx idx) {
|
|
|
|
if (this->IsEmpty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (idx >= size) {
|
|
|
|
assert(false);
|
|
|
|
return; // this should not happen
|
|
|
|
}
|
|
|
|
if (idx == 0) { // just remove the first element, don't need to change the other elements
|
|
|
|
notifications.at(beginIdx).valid = false;
|
|
|
|
beginIdx = (beginIdx + 1) % notifications.size();
|
|
|
|
} else {
|
|
|
|
// overwrite the specified entry by moving all later messages one index to the front
|
|
|
|
for (size_t i = idx; i < size - 1; ++i) {
|
|
|
|
this->At(i) = this->At(i + 1);
|
|
|
|
}
|
|
|
|
this->At(size - 1).valid = false;
|
|
|
|
}
|
|
|
|
--size;
|
|
|
|
}
|
2020-10-20 14:57:39 -04:00
|
|
|
|
2022-05-19 13:59:09 -04:00
|
|
|
void NotificationManager::Dismiss(NotificationManager::Notification::Id id) {
|
|
|
|
NotificationManager::Notification::Idx idx = this->IndexOf(id);
|
|
|
|
if (idx == this->size) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this->DismissIdx(idx);
|
2020-10-20 14:57:39 -04:00
|
|
|
}
|
|
|
|
|
2022-05-19 13:59:09 -04:00
|
|
|
bool NotificationManager::AreNewNotificationsAvailable() const {
|
2020-10-20 14:57:39 -04:00
|
|
|
return newNotification;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NotificationManager::ClearNewNotificationFlag() {
|
|
|
|
return newNotification.exchange(false);
|
|
|
|
}
|
|
|
|
|
2020-10-21 16:15:02 -04:00
|
|
|
size_t NotificationManager::NbNotifications() const {
|
2022-05-19 13:59:09 -04:00
|
|
|
return size;
|
2020-10-21 16:15:02 -04:00
|
|
|
}
|
|
|
|
|
2021-04-04 06:10:47 -04:00
|
|
|
const char* NotificationManager::Notification::Message() const {
|
2021-04-18 13:28:14 -04:00
|
|
|
const char* itField = std::find(message.begin(), message.begin() + size - 1, '\0');
|
|
|
|
if (itField != message.begin() + size - 1) {
|
|
|
|
const char* ptr = (itField) + 1;
|
2021-04-04 06:10:47 -04:00
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
return const_cast<char*>(message.data());
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* NotificationManager::Notification::Title() const {
|
2021-04-18 13:28:14 -04:00
|
|
|
const char* itField = std::find(message.begin(), message.begin() + size - 1, '\0');
|
|
|
|
if (itField != message.begin() + size - 1) {
|
2021-04-04 06:10:47 -04:00
|
|
|
return message.data();
|
|
|
|
}
|
|
|
|
return {};
|
|
|
|
}
|