mirror of
https://github.com/usatiuk/cardboy.git
synced 2025-10-28 23:27:49 +01:00
more fixes
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
#include "cardboy/sdk/app_framework.hpp"
|
||||
#include "cardboy/sdk/app_system.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <ctime>
|
||||
@@ -24,6 +25,20 @@ constexpr std::uint32_t kUnlockHoldMs = 1500;
|
||||
using Framebuffer = typename AppContext::Framebuffer;
|
||||
using Clock = typename AppContext::Clock;
|
||||
|
||||
constexpr std::array<std::uint8_t, font16x8::kGlyphHeight> kArrowUpGlyph{0b00011000, 0b00111100, 0b01111110,
|
||||
0b11111111, 0b00011000, 0b00011000,
|
||||
0b00011000, 0b00011000, 0b00011000,
|
||||
0b00011000, 0b00011000, 0b00011000,
|
||||
0b00011000, 0b00011000, 0b00000000,
|
||||
0b00000000};
|
||||
|
||||
constexpr std::array<std::uint8_t, font16x8::kGlyphHeight> kArrowDownGlyph{0b00000000, 0b00000000, 0b00011000,
|
||||
0b00011000, 0b00011000, 0b00011000,
|
||||
0b00011000, 0b00011000, 0b00011000,
|
||||
0b00011000, 0b00011000, 0b11111111,
|
||||
0b01111110, 0b00111100, 0b00011000,
|
||||
0b00000000};
|
||||
|
||||
struct TimeSnapshot {
|
||||
bool hasWallTime = false;
|
||||
int hour24 = 0;
|
||||
@@ -264,6 +279,30 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
static void drawArrowGlyph(Framebuffer& fb, int x, int y,
|
||||
const std::array<std::uint8_t, font16x8::kGlyphHeight>& glyph, int scale = 1) {
|
||||
if (scale <= 0)
|
||||
return;
|
||||
for (int row = 0; row < font16x8::kGlyphHeight; ++row) {
|
||||
const std::uint8_t rowBits = glyph[row];
|
||||
for (int col = 0; col < font16x8::kGlyphWidth; ++col) {
|
||||
const auto mask = static_cast<std::uint8_t>(1u << (font16x8::kGlyphWidth - 1 - col));
|
||||
if ((rowBits & mask) == 0)
|
||||
continue;
|
||||
for (int sx = 0; sx < scale; ++sx) {
|
||||
for (int sy = 0; sy < scale; ++sy) {
|
||||
fb.drawPixel(x + col * scale + sx, y + row * scale + sy, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void drawArrow(Framebuffer& fb, int x, int y, bool up, int scale = 1) {
|
||||
const auto& glyph = up ? kArrowUpGlyph : kArrowDownGlyph;
|
||||
drawArrowGlyph(fb, x, y, glyph, scale);
|
||||
}
|
||||
|
||||
static std::string truncateWithEllipsis(std::string_view text, int maxWidth, int scale, int letterSpacing) {
|
||||
if (font16x8::measureText(text, scale, letterSpacing) <= maxWidth)
|
||||
return std::string(text);
|
||||
@@ -423,11 +462,15 @@ private:
|
||||
const int counterWidth = font16x8::measureText(counter, scaleSmall, 1);
|
||||
const int counterX = cardMarginSide + cardWidth - cardPadding - counterWidth;
|
||||
font16x8::drawText(framebuffer, counterX, cardMarginTop + cardPadding, counter, scaleSmall, true, 1);
|
||||
const int arrowX = counterX + (counterWidth - 8) / 2;
|
||||
int arrowY = cardMarginTop + cardPadding + textLineHeight + 1;
|
||||
font16x8::drawText(framebuffer, arrowX, arrowY, "^", scaleSmall, true, 0);
|
||||
arrowY += textLineHeight + 2;
|
||||
font16x8::drawText(framebuffer, arrowX, arrowY, "v", scaleSmall, true, 0);
|
||||
const int arrowWidth = font16x8::kGlyphWidth * scaleSmall;
|
||||
const int arrowSpacing = std::max(1, scaleSmall);
|
||||
const int arrowsTotalWide = arrowWidth * 2 + arrowSpacing;
|
||||
const int arrowX = counterX + (counterWidth - arrowsTotalWide) / 2;
|
||||
const int arrowY = cardMarginTop + cardPadding + textLineHeight + 1;
|
||||
drawArrow(framebuffer, arrowX, arrowY, true, scaleSmall);
|
||||
drawArrow(framebuffer, arrowX + arrowWidth + arrowSpacing, arrowY, false, scaleSmall);
|
||||
const int arrowHeight = font16x8::kGlyphHeight * scaleSmall;
|
||||
cardHeight = std::max(cardHeight, arrowY + arrowHeight - cardMarginTop);
|
||||
}
|
||||
|
||||
if (!bodyLines.empty()) {
|
||||
@@ -450,12 +493,15 @@ private:
|
||||
font16x8::drawText(framebuffer, summaryX, summaryY, summary, scaleSmall, true, 1);
|
||||
|
||||
if (notifications.size() > 1) {
|
||||
int arrowX = (framebuffer.width() - 8) / 2;
|
||||
int arrowY = summaryY + textLineHeight + 1;
|
||||
font16x8::drawText(framebuffer, arrowX, arrowY, "^", scaleSmall, true, 0);
|
||||
arrowY += textLineHeight + 2;
|
||||
font16x8::drawText(framebuffer, arrowX, arrowY, "v", scaleSmall, true, 0);
|
||||
cardHeight = std::max(cardHeight, arrowY + textLineHeight - cardMarginTop);
|
||||
const int arrowWidth = font16x8::kGlyphWidth * scaleSmall;
|
||||
const int arrowSpacing = std::max(1, scaleSmall);
|
||||
const int arrowsTotalWide = arrowWidth * 2 + arrowSpacing;
|
||||
const int arrowX = (framebuffer.width() - arrowsTotalWide) / 2;
|
||||
const int arrowY = summaryY + textLineHeight + 1;
|
||||
drawArrow(framebuffer, arrowX, arrowY, true, scaleSmall);
|
||||
drawArrow(framebuffer, arrowX + arrowWidth + arrowSpacing, arrowY, false, scaleSmall);
|
||||
const int arrowHeight = font16x8::kGlyphHeight * scaleSmall;
|
||||
cardHeight = std::max(cardHeight, arrowY + arrowHeight - cardMarginTop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ public:
|
||||
struct Notification {
|
||||
std::uint64_t id = 0;
|
||||
std::uint64_t timestamp = 0;
|
||||
std::uint64_t externalId = 0;
|
||||
std::string title;
|
||||
std::string body;
|
||||
bool unread = true;
|
||||
@@ -87,6 +88,7 @@ public:
|
||||
[[nodiscard]] virtual std::vector<Notification> recent(std::size_t limit) const = 0;
|
||||
virtual void markAllRead() = 0;
|
||||
virtual void clear() = 0;
|
||||
virtual void removeByExternalId(std::uint64_t externalId) = 0;
|
||||
};
|
||||
|
||||
struct Services {
|
||||
|
||||
@@ -93,6 +93,7 @@ public:
|
||||
[[nodiscard]] std::vector<Notification> recent(std::size_t limit) const override;
|
||||
void markAllRead() override;
|
||||
void clear() override;
|
||||
void removeByExternalId(std::uint64_t externalId) override;
|
||||
|
||||
private:
|
||||
static constexpr std::size_t kMaxEntries = 8;
|
||||
|
||||
@@ -157,12 +157,21 @@ void DesktopNotificationCenter::pushNotification(Notification notification) {
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
if (notification.externalId != 0) {
|
||||
for (auto it = entries.begin(); it != entries.end();) {
|
||||
if (it->externalId == notification.externalId)
|
||||
it = entries.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
notification.id = nextId++;
|
||||
notification.unread = true;
|
||||
|
||||
if (entries.size() >= kMaxEntries)
|
||||
entries.erase(entries.begin());
|
||||
entries.push_back(std::move(notification));
|
||||
while (entries.size() > kMaxEntries)
|
||||
entries.erase(entries.begin());
|
||||
++revisionCounter;
|
||||
}
|
||||
|
||||
@@ -203,6 +212,23 @@ void DesktopNotificationCenter::clear() {
|
||||
++revisionCounter;
|
||||
}
|
||||
|
||||
void DesktopNotificationCenter::removeByExternalId(std::uint64_t externalId) {
|
||||
if (externalId == 0)
|
||||
return;
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
bool removed = false;
|
||||
for (auto it = entries.begin(); it != entries.end();) {
|
||||
if (it->externalId == externalId) {
|
||||
it = entries.erase(it);
|
||||
removed = true;
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
if (removed)
|
||||
++revisionCounter;
|
||||
}
|
||||
|
||||
DesktopFramebuffer::DesktopFramebuffer(DesktopRuntime& runtime) : runtime(runtime) {}
|
||||
|
||||
int DesktopFramebuffer::width_impl() const { return cardboy::sdk::kDisplayWidth; }
|
||||
|
||||
Reference in New Issue
Block a user