What each person wants to hear about: a setting for each category and each channel.
Categories
The config names the categories, in the order the preferences show them:
categories: [
comments: [label: "Comments", description: "On your stories"],
followers: [label: "New followers", defaults: [email: :weekly]],
mentions: [label: "Mentions", defaults: [email: :on, telegram: :off]],
billing: [label: "Billing", required: true]
]:labeland:description- what the person reads.:defaults- the setting of each channel for a person who has not changed it::on,:off, and for email:dailyor:weekly. A channel not named is:on.:required- its notifications go whatever the settings, and their emails have no link to unsubscribe: receipts, security, the account. Its settings cannot be changed.
Every notifier has a category of the config. Without :categories, any
category is taken, with every channel on, and the preferences show none.
Settings
| Setting | |
|---|---|
"on" | it goes |
"off" | it does not, and the log says when the person turned it off |
"daily", "weekly" | email only: it waits for the person's digest |
Chime.preferences("user:42")
#=> [%{category: %{key: "comments", label: "Comments", ...}, settings: %{"feed" => "on", "email" => "daily"}}, ...]
Chime.put_preference("user:42", :comments, :email, :daily)
#=> :ok
Chime.put_preference("user:42", :billing, :email, :off)
#=> {:error, :required}The feed turned off for a category keeps its notifications out of the feed and its counts; its other channels still go.
A setting is read when each delivery goes, so a person who turns email off now gets none of the emails that wait.
The forms
- In LiveView:
<Chime.Components.preferences id="notifications" chime={@chime} />, a table with a choice for each category and channel, kept as it changes. - In any frontend:
GETandPUT /preferencesofchime_api(see Any frontend).
Digests
A category's email set to "daily" or "weekly" does not go at its
time: its delivery waits, as "digest", with the rest decided (the
conditions of the notifier, the person's other settings). Every hour, a
job finds the people whose digest is due, in their own time zone (the
recipient's :time_zone, UTC without one): at the config's hour, every
day for daily, on its day for weekly.
{Chime, ..., digest: [at: 9, weekly_on: :monday, email: MyApp.ChimeDigest]}The time zones need a time zone database, set as Elixir's:
config :elixir, :time_zone_database, Tz.TimeZoneDatabaseThe digest's email is Chime's (a list of the notifications as the feed
shows them, with links whole from the config's :url), or your module's
email(recipient, items, period); see Chime.Digest. It carries a link
that turns off every email but the required.
Unsubscribing
Each email has a link to turn off its category's emails, and the headers
of one-click unsubscribe; the digest's turns off every email. Mount the
page at the config's :mail_url:
pipeline :mail do
plug :accepts, ["html"]
end
scope "/" do
pipe_through :mail
chime_mail "/notifications/mail", app_name: "MyApp"
endA GET asks first, with a button: mail clients and scanners open links,
and must not unsubscribe anyone. A POST, the button's or a mail
client's one-click, turns the emails off. The link is signed with the
config's :secret_key_base, and does not expire.