mark more channels as unread properly

This commit is contained in:
ouwou
2021-12-25 02:37:31 -05:00
parent 145504bdd6
commit 41d80af128
5 changed files with 66 additions and 4 deletions

View File

@@ -2253,6 +2253,7 @@ void DiscordClient::StoreMessageData(Message &msg) {
// some notes for myself
// a read channel is determined by checking if the channel object's last message id is equal to the read state's last message id
// channels without entries are also unread
// here the absence of an entry in m_unread indicates a read channel and the value is only the mention count since the message doesnt matter
// no entry.id cannot be a guild even though sometimes it looks like it
void DiscordClient::HandleReadyReadState(const ReadyEventData &data) {
@@ -2270,6 +2271,26 @@ void DiscordClient::HandleReadyReadState(const ReadyEventData &data) {
if (it->second > entry.LastMessageID)
m_unread[entry.ID] = entry.MentionCount;
}
// channels that arent in the read state are considered unread
for (const auto &guild : data.Guilds) {
if (!guild.JoinedAt.has_value()) continue; // doubt this can happen but whatever
const auto joined_at = Snowflake::FromISO8601(*guild.JoinedAt);
for (const auto &channel : *guild.Channels) {
if (channel.LastMessageID.has_value()) {
// unread messages from before you joined dont count as unread
if (*channel.LastMessageID < joined_at) continue;
if (std::find_if(data.ReadState.Entries.begin(), data.ReadState.Entries.end(), [id = channel.ID](const ReadStateEntry &e) {
return e.ID == id;
}) == data.ReadState.Entries.end()) {
// cant be unread if u cant even see the channel
// better to check here since HasChannelPermission hits the store
if (HasChannelPermission(GetUserData().ID, channel.ID, Permission::VIEW_CHANNEL))
m_unread[channel.ID] = 0;
}
}
}
}
}
void DiscordClient::HandleReadyGuildSettings(const ReadyEventData &data) {

View File

@@ -1,7 +1,8 @@
#include "snowflake.hpp"
#include "util.hpp"
#include <chrono>
#include <ctime>
#include <iomanip>
#include <chrono>
constexpr static uint64_t DiscordEpochSeconds = 1420070400;
@@ -14,13 +15,13 @@ Snowflake::Snowflake(uint64_t n)
: m_num(n) {}
Snowflake::Snowflake(const std::string &str) {
if (str.size())
if (!str.empty())
m_num = std::stoull(str);
else
m_num = Invalid;
}
Snowflake::Snowflake(const Glib::ustring &str) {
if (str.size())
if (!str.empty())
m_num = std::strtoull(str.c_str(), nullptr, 10);
else
m_num = Invalid;
@@ -38,6 +39,14 @@ Snowflake Snowflake::FromNow() {
return snowflake;
}
Snowflake Snowflake::FromISO8601(std::string_view ts) {
int yr, mon, day, hr, min, sec, tzhr, tzmin;
float milli;
std::sscanf(ts.data(), "%d-%d-%dT%d:%d:%d%f+%d:%d",
&yr, &mon, &day, &hr, &min, &sec, &milli, &tzhr, &tzmin);
return SecondsInterval * (util::TimeToEpoch(yr, mon, day, hr, min, sec) - DiscordEpochSeconds) + static_cast<uint64_t>(milli * static_cast<float>(SecondsInterval));
}
bool Snowflake::IsValid() const {
return m_num != Invalid;
}

View File

@@ -10,6 +10,7 @@ struct Snowflake {
Snowflake(const Glib::ustring &str);
static Snowflake FromNow(); // not thread safe
static Snowflake FromISO8601(std::string_view ts);
bool IsValid() const;
std::string GetLocalTimestamp() const;
@@ -26,7 +27,7 @@ struct Snowflake {
return m_num;
}
const static Snowflake Invalid; // makes sense to me
const static Snowflake Invalid; // makes sense to me
const static uint64_t SecondsInterval = 4194304000ULL; // the "difference" between two snowflakes one second apart
friend void from_json(const nlohmann::json &j, Snowflake &s);