pub struct NotificationArchiveModel { /* private fields */ }Expand description
Shared model — clones share state. Constructed by the install
helper from NotificationArchive + AppPaths; apps reach it
via ctx.app_state::<Rc<NotificationArchiveModel>>().
NotificationLog and NotificationCenterButton
consume this model directly.
Implementations§
Source§impl NotificationArchiveModel
impl NotificationArchiveModel
Sourcepub fn open(
archive: &NotificationArchive,
paths: &AppPaths,
debounce: Duration,
) -> Result<Self, NotificationArchiveError>
pub fn open( archive: &NotificationArchive, paths: &AppPaths, debounce: Duration, ) -> Result<Self, NotificationArchiveError>
Construct from a NotificationArchive config. For
Persistent mode, resolves the path through AppPaths.
Tests use AppPaths::for_testing(tmpdir) + Duration::ZERO
debounce.
Sourcepub fn in_memory() -> Self
pub fn in_memory() -> Self
Convenience: construct an NotificationArchive::InMemory
archive with the default cap, without going through paths.
Mostly useful for tests and apps that explicitly want no
persistence.
Sourcepub fn entries(&self) -> &ListModel<NotificationEntry>
pub fn entries(&self) -> &ListModel<NotificationEntry>
Reactive handle on the entries. Bind to a ListView /
Repeater for live UI.
Sourcepub fn unread_count(&self) -> &Signal<usize>
pub fn unread_count(&self) -> &Signal<usize>
Signal of the unread count. Drives the bell-button badge.
Sourcepub fn version_signal(&self) -> &Signal<u64>
pub fn version_signal(&self) -> &Signal<u64>
Reactive handle on the archive’s mutation version. Widgets
that render the archive (NotificationLog,
NotificationCenterButton) bind to this at
BindingLevel::Rebuild, in every window — one signal is enough
for N of them, see
ToastRegistry::version_signal
for the history of why that had to be said out loud.
pub fn limit(&self) -> usize
Sourcepub fn flush_now(&self) -> Result<(), SettingsFileError>
pub fn flush_now(&self) -> Result<(), SettingsFileError>
Force the persistent backing file to disk synchronously.
No-op for InMemory. Tests call this between mutations and
re-opening the file to verify persistence.
Sourcepub fn push(&self, entry: NotificationEntry)
pub fn push(&self, entry: NotificationEntry)
Push a notice that has just been raised. Inserts at index 0
(newest first), evicts the oldest if the resulting length exceeds
limit. Stamps the entry’s id field from next_id. Bumps
unread_count when the entry is unread (which is the typical case
from a toast push).
If entry.dedup_id matches an existing row, the notice is that row
raised again: an operation that failed this morning and fails again
now, under the same Toast::id. No new row
is inserted. The row moves to the front, takes the entry’s
timestamp, records a
NotificationUpdate and
takes the entry’s read state, which makes it unread again, even when
the notice says exactly what it said before: the log and the bell show
that it happened again. Every other field is merged as
push_update describes.
Sourcepub fn push_update(&self, entry: NotificationEntry)
pub fn push_update(&self, entry: NotificationEntry)
Push an in-place update of a notice that is still on screen: a
progress notice’s next step, or its result. This is what the toast
registry calls when a Toast::id matches a live toast.
If entry.dedup_id matches an existing row, that row is updated in
place: same position, and it keeps the time the notice was raised.
The row then shows the notice as it now stands, the way the live
toast it mirrors does:
title,body,severity,priority,actionsandrouteare the update’s. An update offering no actions leaves the row offering none: a progress notice’s Cancel must not outlive the notice that said the work was cancelled, nor stand in for the Open and See report a finished one offers.groupandsourceare the update’s when it names them, and stay as they were when it does not.id,timestamp(when the notice was raised, which places the row in the log) anddedup_idstay.- A
NotificationUpdateis appended when the update changes what the row shows (its wording, severity or actions), carrying the update’s timestamp and whichever of title and body changed. A row keeps the most recentUPDATE_HISTORY_LIMITof them. An update that repeats the row exactly records nothing and leaves its read state alone. - A change gives the row the update’s read state, which for a toast
is unread.
unread_countcounts rows, so it grows only when the row had been read.
With no matching row (the user cleared it, or it was evicted), the
update is pushed as a new row, like push.
Sourcepub fn mark_read_where(&self, predicate: impl FnMut(&NotificationEntry) -> bool)
pub fn mark_read_where(&self, predicate: impl FnMut(&NotificationEntry) -> bool)
Mark every UNREAD entry matching predicate as read,
decrementing unread_count by exactly how many were flipped.
This is the scoped counterpart of mark_all_read:
a bell scoped to one window/audience must only mark ITS
entries read on close — calling the unscoped mark_all_read
from a scoped bell would incorrectly clear every OTHER
window’s/audience’s unread state too.
Sourcepub fn mark_all_read(&self)
pub fn mark_all_read(&self)
Mark every archived entry as read; reset unread_count to 0.
Called by NotificationCenterButton when its popover closes.
Sourcepub fn clear_where(&self, predicate: impl FnMut(&NotificationEntry) -> bool)
pub fn clear_where(&self, predicate: impl FnMut(&NotificationEntry) -> bool)
Remove every entry matching predicate, decrementing
unread_count for each removed entry that was unread. The
scoped counterpart of clear: a bell scoped to
one window/audience must only clear ITS entries — the unscoped
clear() wipes the ENTIRE shared archive (every window’s
history), which would be wrong for a scoped “Clear” button.
Sourcepub fn remove_by_id(&self, id: u64)
pub fn remove_by_id(&self, id: u64)
Remove the entry with the given stable id (see
NotificationEntry::id — “assigned by the archive on first
push; never reused”). Updates unread_count if the removed entry
was unread. No-op (no version bump) when no entry has that id.
Deliberately id-based rather than index-based: an index is a
snapshot of the list’s shape at the moment it was read, and is
meaningless once anything else — a concurrent peer-process reload
merged in via the live archive, another push, another remove —
has shifted rows out from under it. A caller that captured “the row
I want to dismiss” as an index earlier and replays it later against
a since-mutated list can silently remove the wrong entry; keying
off id instead re-resolves the row’s current position at the
moment of removal, so it always removes the entry the caller meant.
Trait Implementations§
Auto Trait Implementations§
impl !Freeze for NotificationArchiveModel
impl !RefUnwindSafe for NotificationArchiveModel
impl !Send for NotificationArchiveModel
impl !Sync for NotificationArchiveModel
impl !UnwindSafe for NotificationArchiveModel
impl Unpin for NotificationArchiveModel
impl UnsafeUnpin for NotificationArchiveModel
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.impl<T> ErasedDestructor for Twhere
T: 'static,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more