Skip to main content

Module notify

Module notify 

Source
Expand description

Notification levels and mutes, for communities, channels and DMs alike.

Two settings per scope, doing different jobs. Level decides what rings: every message, only your name, or nothing. Mute greys the row, drops its unread weight, and clamps the level to at most Mentions — a volume knob, not an off switch, which is why Nothing is not a synonym for it.

Level resolves down the chain Community → Channel, most specific opinion winning. Mute unions down it: muting a community mutes every channel in it. A scope with no stored row inherits everything, so an untouched account behaves exactly as it did before any of this existed.

Structs§

Resolved
A scope’s settings after the chain has been walked.
ScopePrefs
One scope’s stored settings. None means inherit; suppress_everyone is only ever set at community scope.

Enums§

MessageClass
What a message is, loudest first. Resolved once at classification so a suppressed @everyone is Normal everywhere downstream: notification, ping badge and muted-row count alike.
NotifyLevel
What rings. Ordered loudest first, so the numeric rank orders “quieter”.

Constants§

MUTE_FOREVER
mute_until sentinel for a mute with no end.
MUTE_OFF
mute_until sentinel for “not muted”.

Functions§

all_prefs
apply_wire
Adopt a sibling device’s list wholesale. Returns the scopes whose settings actually moved, so the caller only has to repaint those.
channel_is_listed
Whether channel_id is one its community still lists. A channel nobody lists has no row to open, so its unread can never be seen or cleared.
community_muted_for_chat
Whether a chat’s COMMUNITY is itself silenced, rather than this one room inside it. A surface that stands for the whole space must not grey because one channel is quiet.
everyone_allowed
Whether an authorized @everyone may ping, for a community. Two levers: the App Settings kill switch, which wins outright, and the community’s own choice under it. A channel has no say, deliberately.
everyone_pings_for_chat
Whether an @everyone in this chat still counts as someone calling your name.
in_legacy_mute_list
The predicate the older vector/mutes projection is both WRITTEN and READ with. Publishing one shape and applying another is how an inherited mute ratchets into a permanent per-channel one.
invalidate
Drop the cache so the next warm re-reads the table.
invalidate_live_channels
Forget which channels are listed; their community’s set was rewritten.
is_loaded
Whether the table has actually been read. An unloaded cache answers “default” for every scope, which is indistinguishable from “nothing is stored” — so anything that WRITES state derived from it must check this first, the same rule synced_prefs::is_hydrated applies to publishing.
is_muted_at
legacy_muted_for_chat
in_legacy_mute_list for a chat, stored flag folded in like resolve_chat.
muted_for_chat
next_expiry
The soonest mute expiry still ahead of now_ms, for arming one timer rather than one per mute.
now_ms
passes
Whether a message of this class rings at this level.
prefs
resolve
Walk the chain for one scope. community_id is the channel’s community, or None for a DM or for a community resolving itself.
resolve_chat
A chat’s settings, with its stored muted flag folded in. That flag is the mirror this module keeps for the paths that predate it, and the landing point for a mute arriving over the older vector/mutes projection, so it counts as a mute in its own right rather than being assumed to agree.
resolve_from
The chain arithmetic on its own: level takes the most specific opinion, mute takes either, and the mute clamps the level it hands back.
ring_for_chat
What a chat’s row should badge with: full unread at All, pings at Mentions, nothing at Nothing.
set_level
set_mute
set_prefs
Write a scope through to the database and the cache.
set_suppress_everyone
sweep_expired
Clear every mute whose timer has run out, returning the scopes that just lapsed. Expiry is a write rather than a read: the callers of muted read a cached boolean, and making them all consult the clock instead would be the wrong fix.
to_wire
This device’s table as the publishable projection.
warm
Read the table into memory. Called once when a database is opened, because every badge recount resolves every chat and a lazy load would put a SQLite round trip on that path.