summaryrefslogtreecommitdiff
path: root/src/components/ble/NotificationManager.cpp
blob: 223f6221af24f107ca8a3e96b5fd3255e46ceadd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include "components/ble/NotificationManager.h"
#include <cstring>
#include <algorithm>
#include <cassert>

using namespace Pinetime::Controllers;

constexpr uint8_t NotificationManager::MessageSize;

void NotificationManager::Push(NotificationManager::Notification&& notif) {
  notif.id = GetNextId();
  notif.valid = true;
  newNotification = true;
  if (beginIdx > 0) {
    --beginIdx;
  } else {
    beginIdx = notifications.size() - 1;
  }
  notifications[beginIdx] = std::move(notif);
  if (size < notifications.size()) {
    size++;
  }
}

NotificationManager::Notification::Id NotificationManager::GetNextId() {
  return nextId++;
}

NotificationManager::Notification NotificationManager::GetLastNotification() const {
  if (this->IsEmpty()) {
    return {};
  }
  return this->At(0);
}

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);
}

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);
}

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;
}

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);
}

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);
}

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()) {
    return {};
  }
  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;
}

void NotificationManager::Dismiss(NotificationManager::Notification::Id id) {
  NotificationManager::Notification::Idx idx = this->IndexOf(id);
  if (idx == this->size) {
    return;
  }
  this->DismissIdx(idx);
}

bool NotificationManager::AreNewNotificationsAvailable() const {
  return newNotification;
}

bool NotificationManager::ClearNewNotificationFlag() {
  return newNotification.exchange(false);
}

size_t NotificationManager::NbNotifications() const {
  return size;
}

const char* NotificationManager::Notification::Message() const {
  const char* itField = std::find(message.begin(), message.begin() + size - 1, '\0');
  if (itField != message.begin() + size - 1) {
    const char* ptr = (itField) + 1;
    return ptr;
  }
  return const_cast<char*>(message.data());
}

const char* NotificationManager::Notification::Title() const {
  const char* itField = std::find(message.begin(), message.begin() + size - 1, '\0');
  if (itField != message.begin() + size - 1) {
    return message.data();
  }
  return {};
}