3 lines
950 KiB
JavaScript
3 lines
950 KiB
JavaScript
(function () {
|
||
window.DENO_DOC_SEARCH_INDEX = {"kind":"search","nodes":[{"id":"namespace_port","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"PORT","file":"api/config.ts","doc":"The port the server listens on (GERBEUR_PORT, default 8000).","url":"./api/config.ts/~/PORT.html","deprecated":false},{"id":"namespace_smtps_url","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"SMTPS_URL","file":"api/config.ts","doc":"The smtps:// URL of the server email-service.ts sends mail through (GERBEUR_SMTPS_URL). When it is empty, no email is sent: sign-up sends no welcome, a password reset request does nothing, and there are no digests.","url":"./api/config.ts/~/SMTPS_URL.html","deprecated":false},{"id":"namespace_email_enabled","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"EMAIL_ENABLED","file":"api/config.ts","doc":"Whether the instance sends email, which is whether SMTPS_URL is set. email-service.ts opens its transport by it, and index.html tells the client, whose settings show the digest switches disabled without it.","url":"./api/config.ts/~/EMAIL_ENABLED.html","deprecated":false},{"id":"namespace_from_email","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"FROM_EMAIL","file":"api/config.ts","doc":"The From address of every email (GERBEUR_FROM_EMAIL), as an address or as Name <address>. email-service.ts refuses to load without it when SMTPS_URL is set.","url":"./api/config.ts/~/FROM_EMAIL.html","deprecated":false},{"id":"namespace_welcome_email_body","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"WELCOME_EMAIL_BODY","file":"api/config.ts","doc":"The Markdown of the welcome email sent on registration (GERBEUR_WELCOME_EMAIL_BODY), or null for the built-in one in the EMAIL_LOCALE. api/mail/welcome.ts replaces {{site_name}} and {{username}} in it.","url":"./api/config.ts/~/WELCOME_EMAIL_BODY.html","deprecated":false},{"id":"namespace_email_locale","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"EMAIL_LOCALE","file":"api/config.ts","doc":"The language of every email (GERBEUR_EMAIL_LOCALE). The interface picks each visitor's language in their browser, which the server never learns, so the emails take the instance's. A value that isn't a locale means the source one, English.","url":"./api/config.ts/~/EMAIL_LOCALE.html","deprecated":false},{"id":"namespace_default_style","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"DEFAULT_STYLE","file":"api/config.ts","doc":"The instance's style (GERBEUR_DEFAULT_STYLE). The site shows it until a visitor or their account picks one, through index.html, and the emails that aren't a user's own (the welcome and the password reset) are drawn in it. A value that isn't a style means BASE_STYLE.","url":"./api/config.ts/~/DEFAULT_STYLE.html","deprecated":false},{"id":"namespace_jwt_secret","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"JWT_SECRET","file":"api/config.ts","doc":"The key lib/jwt.ts signs and verifies tokens with (GERBEUR_JWT_SECRET). The server refuses to start without it.","url":"./api/config.ts/~/JWT_SECRET.html","deprecated":false},{"id":"namespace_listen_host","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"LISTEN_HOST","file":"api/config.ts","doc":"The interface the server binds to (GERBEUR_LISTEN_HOST). The default, 0.0.0.0, lets Docker forward the port; 127.0.0.1 keeps it to loopback.","url":"./api/config.ts/~/LISTEN_HOST.html","deprecated":false},{"id":"namespace_public_url","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"PUBLIC_URL","file":"api/config.ts","doc":"The URL visitors reach the server at (GERBEUR_PUBLIC_URL), without a trailing slash. Behind a reverse proxy it must be the outside URL: it is an allowed origin, it tells links to this site's own pages from other links, and it prefixes the image URLs in their previews.","url":"./api/config.ts/~/PUBLIC_URL.html","deprecated":false},{"id":"namespace_frontend_url","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"FRONTEND_URL","file":"api/config.ts","doc":"Points password reset links and the Open Graph tags' page URLs at the frontend when it isn't served from PUBLIC_URL, as with a separate Vite server, and allows it as an origin. It is GERBEUR_FRONTEND_URL, without a trailing slash.","url":"./api/config.ts/~/FRONTEND_URL.html","deprecated":false},{"id":"namespace_db_path","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"DB_PATH","file":"api/config.ts","doc":"The SQLite database file (GERBEUR_DB_PATH). api/test/setup.ts points it at a throwaway file before anything opens the database.","url":"./api/config.ts/~/DB_PATH.html","deprecated":false},{"id":"namespace_uploads_dir","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"UPLOADS_DIR","file":"api/config.ts","doc":"The directory uploads are stored under (GERBEUR_UPLOADS_DIR). Each kind has its subdirectory below, created by the first upload, and each file is named after the id of what it belongs to.","url":"./api/config.ts/~/UPLOADS_DIR.html","deprecated":false},{"id":"namespace_dumps_dir","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"DUMPS_DIR","file":"api/config.ts","doc":"Holds the file of each file dump.","url":"./api/config.ts/~/DUMPS_DIR.html","deprecated":false},{"id":"namespace_avatars_dir","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"AVATARS_DIR","file":"api/config.ts","doc":"Holds each user's avatar.","url":"./api/config.ts/~/AVATARS_DIR.html","deprecated":false},{"id":"namespace_playlist_images_dir","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"PLAYLIST_IMAGES_DIR","file":"api/config.ts","doc":"Holds each playlist's cover.","url":"./api/config.ts/~/PLAYLIST_IMAGES_DIR.html","deprecated":false},{"id":"namespace_attachments_dir","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"ATTACHMENTS_DIR","file":"api/config.ts","doc":"Holds the images pasted into chat messages, comments, dump notes and descriptions. The startup tasks purge those nothing links to.","url":"./api/config.ts/~/ATTACHMENTS_DIR.html","deprecated":false},{"id":"namespace_thumbnails_dir","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"THUMBNAILS_DIR","file":"api/config.ts","doc":"Holds the thumbnails a poster uploads (<id>-custom) and those the thumbnails route generates from file dumps.","url":"./api/config.ts/~/THUMBNAILS_DIR.html","deprecated":false},{"id":"namespace_scaled_dir","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"SCALED_DIR","file":"api/config.ts","doc":"Holds the scaled-down copies of the images above, which lib/ffmpeg.ts makes as they are first asked for, each at its upload's path with its width. It can be emptied at any time: the copies are made again.","url":"./api/config.ts/~/SCALED_DIR.html","deprecated":false},{"id":"namespace_max_image_size_bytes","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"MAX_IMAGE_SIZE_BYTES","file":"api/config.ts","doc":"Caps the size of an image upload, in bytes, for avatars, covers, thumbnails and attachments. lib/upload.ts states it in megabytes in its error.","url":"./api/config.ts/~/MAX_IMAGE_SIZE_BYTES.html","deprecated":false},{"id":"namespace_dump_allowed_mime_prefixes","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"DUMP_ALLOWED_MIME_PREFIXES","file":"api/config.ts","doc":"The MIME type prefixes a file dump may have. dump-service also accepts the exact types of DUMP_ALLOWED_MIME_TYPES.","url":"./api/config.ts/~/DUMP_ALLOWED_MIME_PREFIXES.html","deprecated":false},{"id":"namespace_dump_allowed_mime_types","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"DUMP_ALLOWED_MIME_TYPES","file":"api/config.ts","doc":"The documents and archives a file dump may be, beyond the prefixes.","url":"./api/config.ts/~/DUMP_ALLOWED_MIME_TYPES.html","deprecated":false},{"id":"namespace_pagination_default_limit","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"PAGINATION_DEFAULT_LIMIT","file":"api/config.ts","doc":"The page size when a request names none.","url":"./api/config.ts/~/PAGINATION_DEFAULT_LIMIT.html","deprecated":false},{"id":"namespace_pagination_max_limit","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"PAGINATION_MAX_LIMIT","file":"api/config.ts","doc":"The largest page size a request may ask for.","url":"./api/config.ts/~/PAGINATION_MAX_LIMIT.html","deprecated":false},{"id":"namespace_orphaned_attachments_retention_hours","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"ORPHANED_ATTACHMENTS_RETENTION_HOURS","file":"api/config.ts","doc":"How long an attachment nothing links to is kept before startup purges it.","url":"./api/config.ts/~/ORPHANED_ATTACHMENTS_RETENTION_HOURS.html","deprecated":false},{"id":"namespace_unused_invites_retention_days","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"UNUSED_INVITES_RETENTION_DAYS","file":"api/config.ts","doc":"How long an invite stays usable. invite-service refuses an older one, and the startup tasks purge it.","url":"./api/config.ts/~/UNUSED_INVITES_RETENTION_DAYS.html","deprecated":false},{"id":"namespace_community_refresh_minutes","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"COMMUNITY_REFRESH_MINUTES","file":"api/config.ts","doc":"How often, in minutes, the /community page's figures are recomputed (GERBEUR_COMMUNITY_REFRESH_MINUTES), 15 by default.","url":"./api/config.ts/~/COMMUNITY_REFRESH_MINUTES.html","deprecated":false},{"id":"namespace_og_site_name","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"OG_SITE_NAME","file":"api/config.ts","doc":"The site's name (GERBEUR_SITE_NAME). It is filled into index.html, the OG tags, the icons' manifest and the emails.","url":"./api/config.ts/~/OG_SITE_NAME.html","deprecated":false},{"id":"namespace_site_emoji","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"SITE_EMOJI","file":"api/config.ts","doc":"The emoji that serves as the site's logo (GERBEUR_SITE_EMOJI). The icons script draws the favicons from it, and index.html carries it to the app's header, so changing it needs a restart but no rebuild.","url":"./api/config.ts/~/SITE_EMOJI.html","deprecated":false},{"id":"namespace_bandcampplayer","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"BandcampPlayer","file":"api/config.ts","doc":"How the frontend plays Bandcamp. \"embed\" uses Bandcamp's iframe, which can't autoplay. \"native\" resolves the page's streams through GET /api/bandcamp/tracks and plays them in the app's player, which autoplays and queues an album's tracks.","url":"./api/config.ts/~/BandcampPlayer.html","deprecated":false},{"id":"namespace_bandcamp_player","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"BANDCAMP_PLAYER","file":"api/config.ts","doc":"How the frontend plays Bandcamp (GERBEUR_BANDCAMP_PLAYER), passed to it in index.html. Any value but \"native\" means \"embed\", so a typo falls back to the player that always works.","url":"./api/config.ts/~/BANDCAMP_PLAYER.html","deprecated":false},{"id":"namespace_theme_color","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"THEME_COLOR","file":"api/config.ts","doc":"The background of the generated Apple touch icon, the manifest's colors, and the accent of previews of this site's own pages. index.html's theme-color tags don't follow it.","url":"./api/config.ts/~/THEME_COLOR.html","deprecated":false},{"id":"namespace_allowed_origins","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"ALLOWED_ORIGINS","file":"api/config.ts","doc":"The origins that CORS in main.ts and the WebSocket route accept. They are PUBLIC_URL, FRONTEND_URL and the comma-separated GERBEUR_ALLOWED_ORIGINS.","url":"./api/config.ts/~/ALLOWED_ORIGINS.html","deprecated":false},{"id":"namespace_federation_allow_private","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"FEDERATION_ALLOW_PRIVATE","file":"api/config.ts","doc":"Lets federated sign-in reach instances on private addresses, localhost among them, and over plain http (GERBEUR_FEDERATION_ALLOW_PRIVATE=1), so that two instances on one machine can trust each other in development. Off, remote/gerbeur-instance.ts reaches only public https instances, since an identity is only as safe as the connection it came over.","url":"./api/config.ts/~/FEDERATION_ALLOW_PRIVATE.html","deprecated":false},{"id":"namespace_federation","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"FEDERATION","file":"api/config.ts","doc":"Which ways federated sign-in goes, each on unless set to 0.incoming (GERBEUR_FEDERATION_INCOMING): users of other instances sign in here. Off, the login and register pages offer no other instance, /manage lists only the blocked ones, which this instance's users can't sign in to (and none with outgoing off too), federation-service.ts refuses their sign-ins, and the accounts that came from one are signed out (getSessionState) until it is on again. Their homes' events are still applied, so that none is lost meanwhile.outgoing (GERBEUR_FEDERATION_OUTGOING): this instance's users sign in to others. Off, identity-provider-service.ts lets no instance sign them in, and its metadata says so, which the others check before sending anyone here to sign in. The settings page lists no instances, since at startup main.ts withdraws every grant they gave, which signs them out there.index.html tells the client both. An object, so that the tests can turn one off for a while.","url":"./api/config.ts/~/FEDERATION.html","deprecated":false},{"id":"namespace_federation","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FEDERATION.incoming","file":"api/config.ts","doc":"","url":"./api/config.ts/~/FEDERATION.incoming.html","deprecated":false},{"id":"namespace_federation","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FEDERATION.outgoing","file":"api/config.ts","doc":"","url":"./api/config.ts/~/FEDERATION.outgoing.html","deprecated":false},{"id":"namespace_db","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"db","file":"api/db/connection.ts","doc":"Serves every query of the server, as its only connection. Its queries are synchronous, so each one blocks the event loop while it runs.","url":"./api/db/connection.ts/~/db.html","deprecated":false},{"id":"namespace_transaction","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"transaction","file":"api/db/connection.ts","doc":"Runs fn in a transaction, so its writes commit together, in one commit rather than one each, and a throw rolls them all back and rethrows. A call inside another joins the outer transaction. fn must be synchronous: an await would commit before the rest of it runs.","url":"./api/db/connection.ts/~/transaction.html","deprecated":false},{"id":"namespace_runmigrations","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"runMigrations","file":"api/db/migrate.ts","doc":"Applies each migration db hasn't recorded yet, in order, each in its own transaction.","url":"./api/db/migrate.ts/~/runMigrations.html","deprecated":false},{"id":"namespace_up","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"up","file":"api/db/migrations/0001_comment_likes.ts","doc":"Run once by runMigrations. Existing comments start with no likes, and a database made from schema.sql already has both.","url":"./api/db/migrations/0001_comment_likes.ts/~/up.html","deprecated":false},{"id":"namespace_up","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"up","file":"api/db/migrations/0002_dump_thumbnail.ts","doc":"Run once by runMigrations. Existing dumps keep their fetched thumbnails, and a database made from schema.sql already has the column.","url":"./api/db/migrations/0002_dump_thumbnail.ts/~/up.html","deprecated":false},{"id":"namespace_up","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"up","file":"api/db/migrations/0003_dump_backlinks.ts","doc":"Run once by runMigrations. It doesn't scan the notes and comments already posted, so their links are recorded only once they are edited.","url":"./api/db/migrations/0003_dump_backlinks.ts/~/up.html","deprecated":false},{"id":"namespace_up","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"up","file":"api/db/migrations/0004_user_roles.ts","doc":"Run once by runMigrations. Every user becomes a user, except those with is_admin set, who become admins.","url":"./api/db/migrations/0004_user_roles.ts/~/up.html","deprecated":false},{"id":"namespace_up","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"up","file":"api/db/migrations/0005_drop_is_admin.ts","doc":"Run once by runMigrations, after 0004. A database made from schema.sql never had the column.","url":"./api/db/migrations/0005_drop_is_admin.ts/~/up.html","deprecated":false},{"id":"namespace_up","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"up","file":"api/db/migrations/0006_categories.ts","doc":"Run once by runMigrations. Existing dumps start in no category, and a database made from schema.sql already has both tables.","url":"./api/db/migrations/0006_categories.ts/~/up.html","deprecated":false},{"id":"namespace_up","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"up","file":"api/db/migrations/0007_password_reset_tokens.ts","doc":"Run once by runMigrations. A database made from schema.sql already has the table.","url":"./api/db/migrations/0007_password_reset_tokens.ts/~/up.html","deprecated":false},{"id":"namespace_up","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"up","file":"api/db/migrations/0008_chat_messages.ts","doc":"Run once by runMigrations. A database made from schema.sql already has the table.","url":"./api/db/migrations/0008_chat_messages.ts/~/up.html","deprecated":false},{"id":"namespace_up","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"up","file":"api/db/migrations/0009_chat_reply.ts","doc":"Run once by runMigrations. Existing messages reply to nothing, and a database made from schema.sql already has the column.","url":"./api/db/migrations/0009_chat_reply.ts/~/up.html","deprecated":false},{"id":"namespace_up","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"up","file":"api/db/migrations/0010_youtube_embed_start.ts","doc":"Run once by runMigrations. It leaves alone an embed URL that already has a start, and a row whose rich_content doesn't parse.","url":"./api/db/migrations/0010_youtube_embed_start.ts/~/up.html","deprecated":false},{"id":"namespace_up","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"up","file":"api/db/migrations/0011_split_favicon_thumbnail.ts","doc":"Run once by runMigrations. It leaves alone a row that already has a faviconUrl, and one whose rich_content doesn't parse. 0012 undoes its mistakes.","url":"./api/db/migrations/0011_split_favicon_thumbnail.ts/~/up.html","deprecated":false},{"id":"namespace_up","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"up","file":"api/db/migrations/0012_fix_favicon_reclassification.ts","doc":"Run once by runMigrations. It moves a faviconUrl back to thumbnailUrl only when 0011's rule takes it for an icon and this one doesn't. That also catches the ones a later fetch stored that this rule doesn't recognise, such as a logo.svg. It then moves the icons 0011 missed.","url":"./api/db/migrations/0012_fix_favicon_reclassification.ts/~/up.html","deprecated":false},{"id":"namespace_up","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"up","file":"api/db/migrations/0013_dump_url_canonical.ts","doc":"Run once by runMigrations. It fills only the keys still NULL, and leaves NULL a URL that isn't http(s).","url":"./api/db/migrations/0013_dump_url_canonical.ts/~/up.html","deprecated":false},{"id":"namespace_up","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"up","file":"api/db/migrations/0014_chat_read_state.ts","doc":"Run once by runMigrations. Existing users start with every message read, instead of the whole history unread. A user created later starts with a NULL chat_read_at, which chat-service reads as the user's creation time.","url":"./api/db/migrations/0014_chat_read_state.ts/~/up.html","deprecated":false},{"id":"namespace_up","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"up","file":"api/db/migrations/0015_token_revocation.ts","doc":"Run once by runMigrations. Existing users start with NULL, which revokes no token.","url":"./api/db/migrations/0015_token_revocation.ts/~/up.html","deprecated":false},{"id":"namespace_up","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"up","file":"api/db/migrations/0016_performance_indexes.ts","doc":"Run once by runMigrations. A database made from schema.sql already has these indexes.","url":"./api/db/migrations/0016_performance_indexes.ts/~/up.html","deprecated":false},{"id":"namespace_up","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"up","file":"api/db/migrations/0017_case_insensitive_users.ts","doc":"Run once by runMigrations. It refuses to run, naming the clashes, when two accounts already share a name or an address in some case: which one keeps it is for whoever runs the site to decide, by editing one of them.","url":"./api/db/migrations/0017_case_insensitive_users.ts/~/up.html","deprecated":false},{"id":"namespace_up","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"up","file":"api/db/migrations/0018_attachment_resource_type.ts","doc":"Run once by runMigrations. Existing bound attachments get the type of the table that holds their resource; one whose resource is gone gets none, and the startup purge deletes it. A database made from schema.sql already has the column.","url":"./api/db/migrations/0018_attachment_resource_type.ts/~/up.html","deprecated":false},{"id":"namespace_up","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"up","file":"api/db/migrations/0019_user_settings.ts","doc":"Run once by runMigrations. Existing users get no row, so they start with the defaults, digests on, like a new account.","url":"./api/db/migrations/0019_user_settings.ts/~/up.html","deprecated":false},{"id":"namespace_up","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"up","file":"api/db/migrations/0020_digest_schedule.ts","doc":"Run once by runMigrations. Every user present gets both cadences, with a first period that ends at some hour of the coming week or month, picked from their id: the digests start trickling out after the deploy instead of all leaving a week later. Users created later are scheduled by the service when it first sees them.","url":"./api/db/migrations/0020_digest_schedule.ts/~/up.html","deprecated":false},{"id":"namespace_up","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"up","file":"api/db/migrations/0021_page_urls.ts","doc":"Run once by runMigrations. On a database made from schema.sql the tables and indexes exist and there is nothing to re-slug or rewrite.","url":"./api/db/migrations/0021_page_urls.ts/~/up.html","deprecated":false},{"id":"namespace_up","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"up","file":"api/db/migrations/0022_reserve_community.ts","doc":"Run once by runMigrations.","url":"./api/db/migrations/0022_reserve_community.ts/~/up.html","deprecated":false},{"id":"namespace_up","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"up","file":"api/db/migrations/0023_mention_everyone.ts","doc":"Run once by runMigrations. The messages that a moderator or an admin already sent with @everyone get the flag, so that editing one later doesn't notify everyone of an old message; none is notified now. A user named everyone, in any case, is renamed to the first free everyone_2, everyone_3…, with no alias left behind, and an alias everyone is dropped. Both are logged.","url":"./api/db/migrations/0023_mention_everyone.ts/~/up.html","deprecated":false},{"id":"namespace_up","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"up","file":"api/db/migrations/0024_federation.ts","doc":"Run once by runMigrations. Nothing exists to convert, since every account so far is local, but authorize and federation become the pages of a sign-in, so a category that had one as its slug is renamed.","url":"./api/db/migrations/0024_federation.ts/~/up.html","deprecated":false},{"id":"namespace_up","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"up","file":"api/db/migrations/0025_playlist_categories.ts","doc":"Run once by runMigrations. Every existing category becomes a dump category, filing the same dumps.SQLite can't change a table's UNIQUE constraints in place, so categories is rebuilt. foreign_keys can't be switched off inside the runner's transaction, and dropping categories would then empty dump_categories through its cascade, so both are read, dropped child first, made anew as in schema.sql, and refilled. A database made from schema.sql already has the kind column and is left as it is.","url":"./api/db/migrations/0025_playlist_categories.ts/~/up.html","deprecated":false},{"id":"namespace_runstartuptasks","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"runStartupTasks","file":"api/db/startup.ts","doc":"Runs after the migrations, each time the server starts. It deletes used or expired reset tokens, invites past their validity, and attachments nothing links to or whose resource is gone. On an instance with no users, it creates the user admin with the password admin, which whoever installs it must change.","url":"./api/db/startup.ts/~/runStartupTasks.html","deprecated":false},{"id":"namespace_apistatus","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"APIStatus","file":"api/lib/api-exception.ts","doc":"Passed to an APIException; any other status is a type error.","url":"./api/lib/api-exception.ts/~/APIStatus.html","deprecated":false},{"id":"namespace_apiexception","kind":[{"char":"c","kind":"Class","title":"Class"}],"name":"APIException","file":"api/lib/api-exception.ts","doc":"Thrown by a route, a service or a remote fetch to answer the request with an error. The error middleware sends it as an APIFailure, message included, so the message must be fit for the user. Use 401 for a caller who isn't signed in, 403 for one who is but may not, and 404 rather than 403 when the caller mustn't learn that the thing exists.","url":"./api/lib/api-exception.ts/~/APIException.html","deprecated":false},{"id":"namespace_apiexception","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"APIException.prototype.code","file":"api/lib/api-exception.ts","doc":"","url":"./api/lib/api-exception.ts/~/APIException.prototype.code.html","deprecated":false},{"id":"namespace_apiexception","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"APIException.prototype.status","file":"api/lib/api-exception.ts","doc":"","url":"./api/lib/api-exception.ts/~/APIException.prototype.status.html","deprecated":false},{"id":"namespace_authenticate","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"authenticate","file":"api/lib/auth.ts","doc":"Returns the payload of a valid session token, or null. Besides the signature and expiry, it refuses a token whose user is gone or which predates a password change. The returned role comes from the database, not the token, since a token lasts 7 days and a role can change under it.","url":"./api/lib/auth.ts/~/authenticate.html","deprecated":false},{"id":"namespace_authenticatemedia","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"authenticateMedia","file":"api/lib/auth.ts","doc":"Returns the user id behind the ?token= of a file, thumbnail or playlist cover URL, or null when it isn't valid. A session token is accepted too, for clients from before media tokens.","url":"./api/lib/auth.ts/~/authenticateMedia.html","deprecated":false},{"id":"namespace_parseoptionalauth","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"parseOptionalAuth","file":"api/lib/auth.ts","doc":"Returns the caller's user id on a route open to anonymous callers, or null when the request has no token. A placeholder such as Bearer undefined counts as no token. An invalid token throws instead of reading as anonymous, so that a stale session gets a 401 the client signs out on, rather than a misleading 404 on a private resource.","url":"./api/lib/auth.ts/~/parseOptionalAuth.html","deprecated":false},{"id":"namespace_youtubehost","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"youtubeHost","file":"api/lib/canonical-url.ts","doc":"Returns u's host in lower case and without \"www.\", when it is one of YouTube's (youtu.be aside), and null otherwise. The YouTube preview provider uses it too, so both agree on what a YouTube link is.","url":"./api/lib/canonical-url.ts/~/youtubeHost.html","deprecated":false},{"id":"namespace_youtubevideoid","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"youtubeVideoId","file":"api/lib/canonical-url.ts","doc":"Returns the id of the video a YouTube URL points at, in any of the shapes people paste (youtu.be/ID, /watch?v=ID, /embed/ID, /shorts/ID, /live/ID), and null for any other URL. host is lower case, without \"www.\". The canonical key drops the timestamp, since the same video linked at 2:30 is still a repost; the YouTube provider reads it separately.","url":"./api/lib/canonical-url.ts/~/youtubeVideoId.html","deprecated":false},{"id":"namespace_canonicalizeurl","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"canonicalizeUrl","file":"api/lib/canonical-url.ts","doc":"Returns the canonical key of raw, or null when it isn't an http(s) URL. A YouTube video or playlist becomes one fixed URL whatever shape it came in.","url":"./api/lib/canonical-url.ts/~/canonicalizeUrl.html","deprecated":false},{"id":"namespace_rgba","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"Rgba","file":"api/lib/css-color.ts","doc":"An sRGB color with its alpha, each channel 0–255 and alpha 0–1.","url":"./api/lib/css-color.ts/~/Rgba.html","deprecated":false},{"id":"namespace_rgba","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Rgba.r","file":"api/lib/css-color.ts","doc":"","url":"./api/lib/css-color.ts/~/Rgba.r.html","deprecated":false},{"id":"namespace_rgba","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Rgba.g","file":"api/lib/css-color.ts","doc":"","url":"./api/lib/css-color.ts/~/Rgba.g.html","deprecated":false},{"id":"namespace_rgba","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Rgba.b","file":"api/lib/css-color.ts","doc":"","url":"./api/lib/css-color.ts/~/Rgba.b.html","deprecated":false},{"id":"namespace_rgba","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Rgba.a","file":"api/lib/css-color.ts","doc":"","url":"./api/lib/css-color.ts/~/Rgba.a.html","deprecated":false},{"id":"namespace_parsecsscolor","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"parseCssColor","file":"api/lib/css-color.ts","doc":"Returns the color text writes as a hex (3, 4, 6 or 8 digits), an rgb() or rgba() of numbers or percentages, or one of the common names; undefined for any other form. Channels out of range are clamped.","url":"./api/lib/css-color.ts/~/parseCssColor.html","deprecated":false},{"id":"namespace_hexof","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"hexOf","file":"api/lib/css-color.ts","doc":"Writes color as a lowercase #rrggbb, its alpha dropped.","url":"./api/lib/css-color.ts/~/hexOf.html","deprecated":false},{"id":"namespace_resolvemediadump","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"resolveMediaDump","file":"api/lib/dump-media.ts","doc":"Returns dump dumpId as the viewer of ctx's ?token= may see it, and the Cache-Control its media get: kept for good under a URL naming the file's current version (?v=, as dumpFileVersion gives), revalidated under any other, and never in a shared cache for a private dump. It also keeps the token out of the Referer of whatever the response links to.","url":"./api/lib/dump-media.ts/~/resolveMediaDump.html","deprecated":false},{"id":"namespace_generatedpaths","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"generatedPaths","file":"api/lib/ffmpeg.ts","doc":"Returns where the still and the waveform generated from dump dumpId's upload are kept.","url":"./api/lib/ffmpeg.ts/~/generatedPaths.html","deprecated":false},{"id":"namespace_scaledformat","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"ScaledFormat","file":"api/lib/ffmpeg.ts","doc":"The formats a scaled copy comes in: WebP for a browser, and a JPEG or a PNG for what doesn't read it, as some mail clients don't.","url":"./api/lib/ffmpeg.ts/~/ScaledFormat.html","deprecated":false},{"id":"namespace_scaledimagepath","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"scaledImagePath","file":"api/lib/ffmpeg.ts","doc":"Returns where the copy of the upload at srcPath scaled to width is kept, in format: under SCALED_DIR, at the upload's own path below UPLOADS_DIR.","url":"./api/lib/ffmpeg.ts/~/scaledImagePath.html","deprecated":false},{"id":"namespace_removescaledimages","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"removeScaledImages","file":"api/lib/ffmpeg.ts","doc":"Deletes the scaled copies of the upload at srcPath, once it is deleted. One that is replaced needs no call: its copies are made again, being older than it (ensureGenerated).","url":"./api/lib/ffmpeg.ts/~/removeScaledImages.html","deprecated":false},{"id":"namespace_removegeneratedmedia","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"removeGeneratedMedia","file":"api/lib/ffmpeg.ts","doc":"Deletes what was generated from dump dumpId's upload, once dump-service has replaced or deleted it. The routes make them again from a new one.","url":"./api/lib/ffmpeg.ts/~/removeGeneratedMedia.html","deprecated":false},{"id":"namespace_videostill","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"videoStill","file":"api/lib/ffmpeg.ts","doc":"Writes a 320-pixel-wide JPEG still of a video, one second in.","url":"./api/lib/ffmpeg.ts/~/videoStill.html","deprecated":false},{"id":"namespace_imagetraits","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ImageTraits","file":"api/lib/ffmpeg.ts","doc":"What scaleImage is told of the image it scales, which scalableImage (lib/upload.ts) reads from its first bytes.","url":"./api/lib/ffmpeg.ts/~/ImageTraits.html","deprecated":false},{"id":"namespace_imagetraits","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ImageTraits.orientation","file":"api/lib/ffmpeg.ts","doc":"The EXIF orientation to turn the image by, 1 when it is upright.","url":"./api/lib/ffmpeg.ts/~/ImageTraits.orientation.html","deprecated":false},{"id":"namespace_imagetraits","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ImageTraits.animated","file":"api/lib/ffmpeg.ts","doc":"Whether its frames are an animation, as a GIF's are. A still may hold more than one image too, a phone's JPEG carrying a gain map or a depth map after the photo, and ffmpeg reads each as a frame.","url":"./api/lib/ffmpeg.ts/~/ImageTraits.animated.html","deprecated":false},{"id":"namespace_scaleimage","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"scaleImage","file":"api/lib/ffmpeg.ts","doc":"Writes a copy of an image at most width wide, never wider than the image itself, as a WebP unless format names another. WebP keeps a PNG's transparency and a GIF's animation, at a fraction of either's bytes.","url":"./api/lib/ffmpeg.ts/~/scaleImage.html","deprecated":false},{"id":"namespace_scaleimagebytes","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"scaleImageBytes","file":"api/lib/ffmpeg.ts","doc":"Returns bytes, an image held in memory, scaled as scaleImage does, or null when it can't be, because ffmpeg is missing or failed. The image proxy scales what it fetched with it, and keeps the result itself.","url":"./api/lib/ffmpeg.ts/~/scaleImageBytes.html","deprecated":false},{"id":"namespace_audiowaveform","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"audioWaveform","file":"api/lib/ffmpeg.ts","doc":"Writes the waveform of the audio file srcPath as the waveform route's whole response, so the route serves it as a file, with its ETag.","url":"./api/lib/ffmpeg.ts/~/audioWaveform.html","deprecated":false},{"id":"namespace_ensuregenerated","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"ensureGenerated","file":"api/lib/ffmpeg.ts","doc":"Makes outPath with generate unless it exists. Resolves false when it can't be made, because ffmpeg is missing or failed.With srcPath, the file it is made from, outPath takes that file's date, and is made again when the two differ: an upload replaced in place, as an avatar or a cover is, gets new copies without anyone deleting the old. Without it, the caller deletes outPath when its source changes.","url":"./api/lib/ffmpeg.ts/~/ensureGenerated.html","deprecated":false},{"id":"namespace_sweepgeneratedmedia","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"sweepGeneratedMedia","file":"api/lib/ffmpeg.ts","doc":"Deletes the generated files nothing serves any more, and returns how many: the scaled copies of an upload that is gone, which the services' own removals missed or never made, as for a user's avatar; the previews of image dumps under their former name, <id>.preview.jpg or .png, which the scaled copies replaced; and the temporary files a generation left unfinished. Nothing else of THUMBNAILS_DIR is touched, the custom thumbnails kept there being uploads.","url":"./api/lib/ffmpeg.ts/~/sweepGeneratedMedia.html","deprecated":false},{"id":"namespace_generatedmediasweepjob","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"generatedMediaSweepJob","file":"api/lib/ffmpeg.ts","doc":"Runs sweepGeneratedMedia a minute after the server starts, which clears what a new version no longer uses as soon as it is deployed, then once a day. main.ts starts it.","url":"./api/lib/ffmpeg.ts/~/generatedMediaSweepJob.html","deprecated":false},{"id":"namespace_loadindexhtml","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"loadIndexHtml","file":"api/lib/index-html.ts","doc":"Returns ${root}/index.html with the site name, emoji, icon version, Bandcamp player mode, default style, and whether email and each way of federated sign-in are on filled in.","url":"./api/lib/index-html.ts/~/loadIndexHtml.html","deprecated":false},{"id":"namespace_createpasswordresettoken","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"createPasswordResetToken","file":"api/lib/jwt.ts","doc":"Signs a password reset token for userId, valid for an hour. The token isn't single-use by itself: requestPasswordReset stores it, and resetPassword marks it used.","url":"./api/lib/jwt.ts/~/createPasswordResetToken.html","deprecated":false},{"id":"namespace_verifypasswordresettoken","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"verifyPasswordResetToken","file":"api/lib/jwt.ts","doc":"Returns the payload of a password reset token, or null when it is invalid, expired or another kind of token. Whether it was used is the caller's check.","url":"./api/lib/jwt.ts/~/verifyPasswordResetToken.html","deprecated":false},{"id":"namespace_createjwt","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"createJWT","file":"api/lib/jwt.ts","doc":"Signs a session token carrying payload, valid for 7 days. issueTokens issues it on sign-up, sign-in and password change, and the client sends it as a bearer token.","url":"./api/lib/jwt.ts/~/createJWT.html","deprecated":false},{"id":"namespace_issuetokens","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"issueTokens","file":"api/lib/jwt.ts","doc":"Returns a new session token and media token for user, as sign-up (POST /api/users), sign-in (POST /api/sessions) and a password change (PUT /api/me/password) answer them.","url":"./api/lib/jwt.ts/~/issueTokens.html","deprecated":false},{"id":"namespace_createmediatoken","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"createMediaToken","file":"api/lib/jwt.ts","doc":"Signs a media token for userId, valid for 7 days. Media elements can't send an Authorization header, so the URLs of private files, thumbnails and playlist covers carry this token as ?token=, where it lands in logs and browser history. It only reads media, so a leaked URL doesn't expose the account.","url":"./api/lib/jwt.ts/~/createMediaToken.html","deprecated":false},{"id":"namespace_verifymediatoken","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"verifyMediaToken","file":"api/lib/jwt.ts","doc":"Returns the user id and issue time of a media token, or null when it is invalid, expired or another kind of token.","url":"./api/lib/jwt.ts/~/verifyMediaToken.html","deprecated":false},{"id":"namespace_verifyjwt","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"verifyJWT","file":"api/lib/jwt.ts","doc":"Returns the payload of a session token whose signature and expiry are valid, or null. Call authenticate (lib/auth.ts) instead, which also checks the token against its user.","url":"./api/lib/jwt.ts/~/verifyJWT.html","deprecated":false},{"id":"namespace_createunsubscribetoken","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"createUnsubscribeToken","file":"api/lib/jwt.ts","doc":"Signs the token of a digest's unsubscribe link, which turns off cadence for userId without signing in. It never expires, so the link in an old email still works; turning the digest back on doesn't revoke it, which is harmless since all it can do is turn it off again.","url":"./api/lib/jwt.ts/~/createUnsubscribeToken.html","deprecated":false},{"id":"namespace_verifyunsubscribetoken","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"verifyUnsubscribeToken","file":"api/lib/jwt.ts","doc":"Returns the user and cadence of an unsubscribe token, or null when it is invalid or another kind of token.","url":"./api/lib/jwt.ts/~/verifyUnsubscribeToken.html","deprecated":false},{"id":"namespace_instancesigningkey","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"InstanceSigningKey","file":"api/lib/jwt.ts","doc":"An instance's key, ready to sign, from importInstanceKey. Its kid names the public half in the instance's JWKS.","url":"./api/lib/jwt.ts/~/InstanceSigningKey.html","deprecated":false},{"id":"namespace_instancesigningkey","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InstanceSigningKey.kid","file":"api/lib/jwt.ts","doc":"","url":"./api/lib/jwt.ts/~/InstanceSigningKey.kid.html","deprecated":false},{"id":"namespace_instancesigningkey","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InstanceSigningKey.privateKey","file":"api/lib/jwt.ts","doc":"","url":"./api/lib/jwt.ts/~/InstanceSigningKey.privateKey.html","deprecated":false},{"id":"namespace_generateinstancekey","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"generateInstanceKey","file":"api/lib/jwt.ts","doc":"Returns a new Ed25519 key pair as JWKs, with a random kid, for instance-key-service.ts to store when the instance has none. The public JWK carries the kid, alg and use a JWKS entry needs.","url":"./api/lib/jwt.ts/~/generateInstanceKey.html","deprecated":false},{"id":"namespace_importinstancekey","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"importInstanceKey","file":"api/lib/jwt.ts","doc":"Returns the stored private JWK privateJwk as a key to sign with.","url":"./api/lib/jwt.ts/~/importInstanceKey.html","deprecated":false},{"id":"namespace_signinstancetoken","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"signInstanceToken","file":"api/lib/jwt.ts","doc":"Signs payload with the instance's key, from issuer (this instance) to audience (the instance it is for), valid for expiresIn, with a random jti. The identity tokens of POST /api/oauth/tokens and the events of the outbox are signed with it.","url":"./api/lib/jwt.ts/~/signInstanceToken.html","deprecated":false},{"id":"namespace_verifyinstancetoken","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"verifyInstanceToken","file":"api/lib/jwt.ts","doc":"Returns the payload of token once its signature checks against jwks, the keys of issuer, and it is addressed to audience and unexpired.","url":"./api/lib/jwt.ts/~/verifyInstanceToken.html","deprecated":false},{"id":"namespace_likepattern","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"likePattern","file":"api/lib/like.ts","doc":"Returns the pattern matching text that contains query, or that starts with it when where is \"prefix\". The SQL must read LIKE ? ESCAPE '\\', which the LIKE fragment spells.","url":"./api/lib/like.ts/~/likePattern.html","deprecated":false},{"id":"namespace_like","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"LIKE","file":"api/lib/like.ts","doc":"Spells LIKE ? ESCAPE '\\', for a likePattern parameter.","url":"./api/lib/like.ts/~/LIKE.html","deprecated":false},{"id":"namespace_parsepagination","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"parsePagination","file":"api/lib/pagination.ts","doc":"Reads the page and limit query parameters of a list route. It never fails: a missing or invalid page reads as 1, and limit is kept between 1 and PAGINATION_MAX_LIMIT.","url":"./api/lib/pagination.ts/~/parsePagination.html","deprecated":false},{"id":"namespace_page","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"Page","file":"api/lib/pagination.ts","doc":"Returned to the routes by the services' list functions, and sent as PaginatedData.","url":"./api/lib/pagination.ts/~/Page.html","deprecated":false},{"id":"namespace_page","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Page.items","file":"api/lib/pagination.ts","doc":"","url":"./api/lib/pagination.ts/~/Page.items.html","deprecated":false},{"id":"namespace_page","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Page.hasMore","file":"api/lib/pagination.ts","doc":"","url":"./api/lib/pagination.ts/~/Page.hasMore.html","deprecated":false},{"id":"namespace_pageof","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"pageOf","file":"api/lib/pagination.ts","doc":"Turns rows fetched with LIMIT limit + 1 into a page. The extra row, when it comes back, is dropped and tells that another page follows, which spares a COUNT(*) over the whole list.","url":"./api/lib/pagination.ts/~/pageOf.html","deprecated":false},{"id":"namespace_hashpassword","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"hashPassword","file":"api/lib/password.ts","doc":"Hashes password with scrypt and a random salt, as hash.salt in hex, for users.password_hash.","url":"./api/lib/password.ts/~/hashPassword.html","deprecated":false},{"id":"namespace_verifypassword","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"verifyPassword","file":"api/lib/password.ts","doc":"Checks password against a hash made by hashPassword.","url":"./api/lib/password.ts/~/verifyPassword.html","deprecated":false},{"id":"namespace_can","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"can","file":"api/lib/permissions.ts","doc":"Checks whether the caller's role grants permission. The role is the live one authenticate put in the payload, not the token's.","url":"./api/lib/permissions.ts/~/can.html","deprecated":false},{"id":"namespace_playlistmember","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PlaylistMember","file":"api/lib/playlist-members.ts","doc":"The fields of a playlist's dump that isMemberVisibleTo needs. A Dump has them. For its broadcasts, the playlist service reads only these.","url":"./api/lib/playlist-members.ts/~/PlaylistMember.html","deprecated":false},{"id":"namespace_playlistmember","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistMember.id","file":"api/lib/playlist-members.ts","doc":"","url":"./api/lib/playlist-members.ts/~/PlaylistMember.id.html","deprecated":false},{"id":"namespace_playlistmember","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistMember.isPrivate","file":"api/lib/playlist-members.ts","doc":"","url":"./api/lib/playlist-members.ts/~/PlaylistMember.isPrivate.html","deprecated":false},{"id":"namespace_playlistmember","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistMember.userId","file":"api/lib/playlist-members.ts","doc":"The dump's poster, not the playlist's owner.","url":"./api/lib/playlist-members.ts/~/PlaylistMember.userId.html","deprecated":false},{"id":"namespace_ismembervisibleto","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isMemberVisibleTo","file":"api/lib/playlist-members.ts","doc":"Checks whether viewerId may see member in playlist. A public dump is visible to all. A private dump is visible only to the playlist's owner, and only if they posted it: moderators don't see it, and neither does the owner once someone else's dump in their playlist goes private. A null or undefined viewerId is a signed-out viewer.","url":"./api/lib/playlist-members.ts/~/isMemberVisibleTo.html","deprecated":false},{"id":"namespace_datedplaylistmember","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"DatedPlaylistMember","file":"api/lib/playlist-members.ts","doc":"The fields of a playlist's dump that dumpFiguresFor needs: those that tell who may see it, and when it was added. The playlist service reads them for its broadcasts.","url":"./api/lib/playlist-members.ts/~/DatedPlaylistMember.html","deprecated":false},{"id":"namespace_datedplaylistmember","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DatedPlaylistMember.addedAt","file":"api/lib/playlist-members.ts","doc":"","url":"./api/lib/playlist-members.ts/~/DatedPlaylistMember.addedAt.html","deprecated":false},{"id":"namespace_visible_dump_figures","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"VISIBLE_DUMP_FIGURES","file":"api/lib/playlist-members.ts","doc":"The dump_count and last_dump_at columns of a query on playlists p: how many of the playlist's dumps the viewer may see, by isMemberVisibleTo's rule, and when the latest of them was added, null without any. Both read the viewer's id, or \"\" for a signed-out one, as ?1: it is the query's first parameter, and each ? after it takes the next.","url":"./api/lib/playlist-members.ts/~/VISIBLE_DUMP_FIGURES.html","deprecated":false},{"id":"namespace_dumpfiguresfor","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"dumpFiguresFor","file":"api/lib/playlist-members.ts","doc":"Returns what playlist says of its dumps to the viewer, members being all of them: the dumpCount and lastDumpAt that VISIBLE_DUMP_FIGURES reads in a query. The WebSocket service puts them on the playlist each socket is sent.","url":"./api/lib/playlist-members.ts/~/dumpFiguresFor.html","deprecated":false},{"id":"namespace_ratelimit","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"RateLimit","file":"api/lib/rate-limit.ts","doc":"Passed to takeToken by each limited action, which declares its own as a constant.","url":"./api/lib/rate-limit.ts/~/RateLimit.html","deprecated":false},{"id":"namespace_ratelimit","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RateLimit.capacity","file":"api/lib/rate-limit.ts","doc":"How many tokens a full bucket holds, and so the largest burst.","url":"./api/lib/rate-limit.ts/~/RateLimit.capacity.html","deprecated":false},{"id":"namespace_ratelimit","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RateLimit.refill","file":"api/lib/rate-limit.ts","doc":"Tokens regained per second.","url":"./api/lib/rate-limit.ts/~/RateLimit.refill.html","deprecated":false},{"id":"namespace_taketoken","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"takeToken","file":"api/lib/rate-limit.ts","doc":"Takes one token from key's bucket, or returns false when it is empty. The caller picks the key, such as typing:<userId>, and keys by user or account so that more tabs or parallel requests don't buy more tokens.","url":"./api/lib/rate-limit.ts/~/takeToken.html","deprecated":false},{"id":"namespace_ratelimitsweepjob","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"rateLimitSweepJob","file":"api/lib/rate-limit.ts","doc":"Drops the buckets untouched for an hour, every minute. Every limit in use refills within the hour, so such a bucket is full and dropping it changes nothing. main.ts starts it.","url":"./api/lib/rate-limit.ts/~/rateLimitSweepJob.html","deprecated":false},{"id":"namespace_reserved_slugs","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"RESERVED_SLUGS","file":"api/lib/reserved-slugs.ts","doc":"Lists the top-level path segments a category slug may not take: the feed tabs (/hot), the SPA's own pages (src/App.tsx), and api, ws, assets and emojibase, which the server answers before the SPA. Keep it in step with the route table and the build's top-level folders.","url":"./api/lib/reserved-slugs.ts/~/RESERVED_SLUGS.html","deprecated":false},{"id":"namespace_isreservedslug","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isReservedSlug","file":"api/lib/reserved-slugs.ts","doc":"Checks whether slug is one of the RESERVED_SLUGS.","url":"./api/lib/reserved-slugs.ts/~/isReservedSlug.html","deprecated":false},{"id":"namespace_renamereservedcategories","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"renameReservedCategories","file":"api/lib/reserved-slugs.ts","doc":"Renames each category whose slug is now reserved, such as hot, to the first of <slug>-2, <slug>-3… that is free, and logs it. Migration 0021 runs it for v4's words, 0022 for community, 0024 for authorize and federation, and 0025 for playlists.It reads every category: until 0025 gave categories a kind, each was a dump category, and 0025 makes no other. A later migration that reserves more words must leave the playlist categories alone, and limit it to kind = 'dump', which the earlier ones can't, having no such column.","url":"./api/lib/reserved-slugs.ts/~/renameReservedCategories.html","deprecated":false},{"id":"namespace_job","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"Job","file":"api/lib/scheduler.ts","doc":"A recurring task, exported by its module for main.ts to start.","url":"./api/lib/scheduler.ts/~/Job.html","deprecated":false},{"id":"namespace_job","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"Job.run","file":"api/lib/scheduler.ts","doc":"Logs what it did itself, if anything; its errors are logged here.","url":"./api/lib/scheduler.ts/~/Job.run.html","deprecated":false},{"id":"namespace_job","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Job.name","file":"api/lib/scheduler.ts","doc":"Names it in the log, as [digest].","url":"./api/lib/scheduler.ts/~/Job.name.html","deprecated":false},{"id":"namespace_job","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Job.everyMs","file":"api/lib/scheduler.ts","doc":"How long from one run's start to the next.","url":"./api/lib/scheduler.ts/~/Job.everyMs.html","deprecated":false},{"id":"namespace_job","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Job.firstAfterMs","file":"api/lib/scheduler.ts","doc":"How long after the start the first run waits, everyMs by default.","url":"./api/lib/scheduler.ts/~/Job.firstAfterMs.html","deprecated":false},{"id":"namespace_startjobs","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"startJobs","file":"api/lib/scheduler.ts","doc":"Starts running each of jobs on its own timer. A run still going when the next is due makes that one skip, and a run that throws or rejects is logged and the next one runs anyway.","url":"./api/lib/scheduler.ts/~/startJobs.html","deprecated":false},{"id":"namespace_isselfhost","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isSelfHost","file":"api/lib/self-url.ts","doc":"Checks whether host (with its port, as URL.host gives it) is where this site is served, at its public URL or its frontend's.","url":"./api/lib/self-url.ts/~/isSelfHost.html","deprecated":false},{"id":"namespace_isselfurl","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isSelfUrl","file":"api/lib/self-url.ts","doc":"Checks whether url links to one of this site's own dump, user or playlist pages, by parsePagePath; an editor doesn't count. Matched on the host as well as the path: /@bob on some other site is someone else's page, not ours.","url":"./api/lib/self-url.ts/~/isSelfUrl.html","deprecated":false},{"id":"namespace_servefileoptions","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ServeFileOptions","file":"api/lib/serve-file.ts","doc":"Passed to serveFile by its caller, which knows the file's type and how long it may be cached.","url":"./api/lib/serve-file.ts/~/ServeFileOptions.html","deprecated":false},{"id":"namespace_servefileoptions","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ServeFileOptions.mime","file":"api/lib/serve-file.ts","doc":"","url":"./api/lib/serve-file.ts/~/ServeFileOptions.mime.html","deprecated":false},{"id":"namespace_servefileoptions","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ServeFileOptions.cacheControl","file":"api/lib/serve-file.ts","doc":"","url":"./api/lib/serve-file.ts/~/ServeFileOptions.cacheControl.html","deprecated":false},{"id":"namespace_servefileoptions","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ServeFileOptions.ranges","file":"api/lib/serve-file.ts","doc":"Answers a single Range: bytes=… with a 206. The files route sets it, so that audio and video can seek.","url":"./api/lib/serve-file.ts/~/ServeFileOptions.ranges.html","deprecated":false},{"id":"namespace_servefile","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"serveFile","file":"api/lib/serve-file.ts","doc":"Sends a file from disk with an ETag, answering 304 when the client already has it, and single byte ranges when ranges is set. It returns false, having sent nothing, when the file doesn't exist, and leaves the 404 to the caller.","url":"./api/lib/serve-file.ts/~/serveFile.html","deprecated":false},{"id":"namespace_emojitocodepoint","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"emojiToCodepoint","file":"api/lib/site-icons.ts","doc":"Returns the name Twemoji files emoji under: its codepoints in hex, joined with \"-\", without variation selectors (FE0F) unless the emoji is a ZWJ sequence. lib/index-html.ts also uses it as the icon URLs' cache-busting version.","url":"./api/lib/site-icons.ts/~/emojiToCodepoint.html","deprecated":false},{"id":"namespace_generatesiteiconsoptions","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"GenerateSiteIconsOptions","file":"api/lib/site-icons.ts","doc":"Passed to generateSiteIcons by api/scripts/generate-icons.ts, from the site's config.","url":"./api/lib/site-icons.ts/~/GenerateSiteIconsOptions.html","deprecated":false},{"id":"namespace_generatesiteiconsoptions","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"GenerateSiteIconsOptions.emoji","file":"api/lib/site-icons.ts","doc":"","url":"./api/lib/site-icons.ts/~/GenerateSiteIconsOptions.emoji.html","deprecated":false},{"id":"namespace_generatesiteiconsoptions","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"GenerateSiteIconsOptions.outDir","file":"api/lib/site-icons.ts","doc":"Created if missing.","url":"./api/lib/site-icons.ts/~/GenerateSiteIconsOptions.outDir.html","deprecated":false},{"id":"namespace_generatesiteiconsoptions","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"GenerateSiteIconsOptions.siteName","file":"api/lib/site-icons.ts","doc":"","url":"./api/lib/site-icons.ts/~/GenerateSiteIconsOptions.siteName.html","deprecated":false},{"id":"namespace_generatesiteiconsoptions","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"GenerateSiteIconsOptions.bgColor","file":"api/lib/site-icons.ts","doc":"Fills the Apple touch icon, and the manifest's theme and background.","url":"./api/lib/site-icons.ts/~/GenerateSiteIconsOptions.bgColor.html","deprecated":false},{"id":"namespace_generatesiteicons","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"generateSiteIcons","file":"api/lib/site-icons.ts","doc":"Writes favicon.svg, favicon.ico, favicon-<size>x<size>.png (16 to 512), apple-touch-icon.png and manifest.webmanifest into opts.outDir, the directory the site's static files are served from.","url":"./api/lib/site-icons.ts/~/generateSiteIcons.html","deprecated":false},{"id":"namespace_slugkind","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"SlugKind","file":"api/lib/slugify.ts","doc":"A kind of item that has a slug under its owner.","url":"./api/lib/slugify.ts/~/SlugKind.html","deprecated":false},{"id":"namespace_slug_tables","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"SLUG_TABLES","file":"api/lib/slugify.ts","doc":"Where each SlugKind's slugs live.","url":"./api/lib/slugify.ts/~/SLUG_TABLES.html","deprecated":false},{"id":"namespace_slugholder","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"slugHolder","file":"api/lib/slugify.ts","doc":"Returns the id of the item whose current slug or alias is slug in userId's space for kind, or undefined when it is free.","url":"./api/lib/slugify.ts/~/slugHolder.html","deprecated":false},{"id":"namespace_uniqueslug","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"uniqueSlug","file":"api/lib/slugify.ts","doc":"Returns base, or base-2, base-3… cut to fit, whichever is free in userId's space for kind. base must be a valid slug, as slugify makes. The services take it on creating an item, the migration on re-slugging one, inside the transaction that writes it.","url":"./api/lib/slugify.ts/~/uniqueSlug.html","deprecated":false},{"id":"namespace_validateslug","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"validateSlug","file":"api/lib/slugify.ts","doc":"Throws a 400 unless slug is a valid slug, lowercase words of letters and digits joined by hyphens, at most max long. slug-service checks a dump's or a playlist's with it, and category-service a category's, with that kind's own limit.","url":"./api/lib/slugify.ts/~/validateSlug.html","deprecated":false},{"id":"namespace_routestaticfilesfrom","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"routeStaticFilesFrom","file":"api/lib/static.ts","doc":"Returns the middleware that serves a static file from the first of staticPaths that has it, and index.html of the first for any other path. Hashed build output is cached for a year, and a missing chunk is a 404. main.ts passes dist/ then public/.","url":"./api/lib/static.ts/~/routeStaticFilesFrom.html","deprecated":false},{"id":"namespace_ttlcache","kind":[{"char":"c","kind":"Class","title":"Class"}],"name":"TtlCache","file":"api/lib/ttl-cache.ts","doc":"A map whose entries expire ttlMs after they are written, holding maxEntries at most.","url":"./api/lib/ttl-cache.ts/~/TtlCache.html","deprecated":false},{"id":"namespace_ttlcache","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"TtlCache.prototype.get","file":"api/lib/ttl-cache.ts","doc":"Returns the value under key unless it is missing or expired.","url":"./api/lib/ttl-cache.ts/~/TtlCache.prototype.get.html","deprecated":false},{"id":"namespace_ttlcache","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"TtlCache.prototype.set","file":"api/lib/ttl-cache.ts","doc":"Stores value under key from now on, and returns it.","url":"./api/lib/ttl-cache.ts/~/TtlCache.prototype.set.html","deprecated":false},{"id":"namespace_ttlcache","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"TtlCache.prototype.delete","file":"api/lib/ttl-cache.ts","doc":"Removes key, or only when value is still what it holds, so a late failure can't remove the entry that replaced its own.","url":"./api/lib/ttl-cache.ts/~/TtlCache.prototype.delete.html","deprecated":false},{"id":"namespace_ttlcache","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"TtlCache.prototype.clear","file":"api/lib/ttl-cache.ts","doc":"Empties the cache, for the tests' reset between cases.","url":"./api/lib/ttl-cache.ts/~/TtlCache.prototype.clear.html","deprecated":false},{"id":"namespace_detectimagemime","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"detectImageMime","file":"api/lib/upload.ts","doc":"Returns the MIME type of a JPEG, PNG, GIF or WebP image from its magic bytes, or null for anything else. These four are the only image types accepted anywhere. The type the browser declared is never trusted, since the file is later served with the type found here.","url":"./api/lib/upload.ts/~/detectImageMime.html","deprecated":false},{"id":"namespace_validateimageupload","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"validateImageUpload","file":"api/lib/upload.ts","doc":"Checks an uploaded image's size and content, and returns its MIME type, which the route stores to serve the image with.","url":"./api/lib/upload.ts/~/validateImageUpload.html","deprecated":false},{"id":"namespace_scalableimage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ScalableImage","file":"api/lib/upload.ts","doc":"Returned by scalableImage, for scaleImage.","url":"./api/lib/upload.ts/~/ScalableImage.html","deprecated":false},{"id":"namespace_scalableimage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ScalableImage.compat","file":"api/lib/upload.ts","doc":"The format of its copy for a reader without WebP: a JPEG, or a PNG for an image that may be transparent, which a JPEG would fill with black.","url":"./api/lib/upload.ts/~/ScalableImage.compat.html","deprecated":false},{"id":"namespace_scalableimage","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"scalableImage","file":"api/lib/upload.ts","doc":"Returns how to scale the image whose first IMAGE_HEAD_BYTES are head, or null when it is to be served as it is: an animated WebP, which ffmpeg can't read, or anything but a JPEG, PNG, GIF, WebP or BMP.","url":"./api/lib/upload.ts/~/scalableImage.html","deprecated":false},{"id":"namespace_serveimage","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"serveImage","file":"api/lib/upload.ts","doc":"Sends the image at path, of type mime, with cacheControl: a WebP copy at most as wide as the request's ?w= names (shared/image.ts), or as defaultWidth without one, and the image as it is when the request names no width or the copy can't be made. With ?f=compat, the copy is a JPEG, or a PNG for an image that may be transparent, which the digest's emails ask for, since not every mail client reads WebP. Every route that answers one of the site's own images ends here, so each takes both. It resolves false, having sent nothing, when the file is missing.","url":"./api/lib/upload.ts/~/serveImage.html","deprecated":false},{"id":"namespace_serveuploadedfile","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"serveUploadedFile","file":"api/lib/upload.ts","doc":"Serves an uploaded image inline as mime, or scaled down as serveImage does, cached for cacheMaxAge seconds, and only by the browser when isPrivate. It answers 404 and resolves false when the file is missing. The caller checks first that the viewer may see it.","url":"./api/lib/upload.ts/~/serveUploadedFile.html","deprecated":false},{"id":"namespace_replaceuploadedfile","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"replaceUploadedFile","file":"api/lib/upload.ts","doc":"Writes data to filePath, replacing whatever is there only once the whole file is written, so a failed write leaves the old file whole. The upload routes call it before recording the new file, so that clients told of it never fetch it early.","url":"./api/lib/upload.ts/~/replaceUploadedFile.html","deprecated":false},{"id":"namespace_activitykind","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"ActivityKind","file":"api/mail/digest.ts","doc":"The kinds of activity a weekly digest counts.","url":"./api/mail/digest.ts/~/ActivityKind.html","deprecated":false},{"id":"namespace_highlightkind","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"HighlightKind","file":"api/mail/digest.ts","doc":"What a highlight of the weekly digest says happened.","url":"./api/mail/digest.ts/~/HighlightKind.html","deprecated":false},{"id":"namespace_digestdump","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"DigestDump","file":"api/mail/digest.ts","doc":"A dump in a digest's lists, with its links made absolute.","url":"./api/mail/digest.ts/~/DigestDump.html","deprecated":false},{"id":"namespace_digestdump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestDump.title","file":"api/mail/digest.ts","doc":"","url":"./api/mail/digest.ts/~/DigestDump.title.html","deprecated":false},{"id":"namespace_digestdump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestDump.url","file":"api/mail/digest.ts","doc":"","url":"./api/mail/digest.ts/~/DigestDump.url.html","deprecated":false},{"id":"namespace_digestdump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestDump.poster","file":"api/mail/digest.ts","doc":"","url":"./api/mail/digest.ts/~/DigestDump.poster.html","deprecated":false},{"id":"namespace_digestdump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestDump.domain","file":"api/mail/digest.ts","doc":"The link's host, or null for an upload.","url":"./api/mail/digest.ts/~/DigestDump.domain.html","deprecated":false},{"id":"namespace_digestdump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestDump.thumbnail","file":"api/mail/digest.ts","doc":"An absolute image URL, or null to show no image.","url":"./api/mail/digest.ts/~/DigestDump.thumbnail.html","deprecated":false},{"id":"namespace_digestdump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestDump.votes","file":"api/mail/digest.ts","doc":"","url":"./api/mail/digest.ts/~/DigestDump.votes.html","deprecated":false},{"id":"namespace_digestdump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestDump.comments","file":"api/mail/digest.ts","doc":"","url":"./api/mail/digest.ts/~/DigestDump.comments.html","deprecated":false},{"id":"namespace_digestdump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestDump.mine","file":"api/mail/digest.ts","doc":"Posted by the reader, which the lists mark.","url":"./api/mail/digest.ts/~/DigestDump.mine.html","deprecated":false},{"id":"namespace_digestdump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestDump.addedTo","file":"api/mail/digest.ts","doc":"The followed playlist it was added to, when that's why it's listed.","url":"./api/mail/digest.ts/~/DigestDump.addedTo.html","deprecated":false},{"id":"namespace_digesthighlight","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"DigestHighlight","file":"api/mail/digest.ts","doc":"One line of the weekly digest's \"For you\", made from a notification.","url":"./api/mail/digest.ts/~/DigestHighlight.html","deprecated":false},{"id":"namespace_digesthighlight","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestHighlight.kind","file":"api/mail/digest.ts","doc":"","url":"./api/mail/digest.ts/~/DigestHighlight.kind.html","deprecated":false},{"id":"namespace_digesthighlight","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestHighlight.who","file":"api/mail/digest.ts","doc":"Who did it.","url":"./api/mail/digest.ts/~/DigestHighlight.who.html","deprecated":false},{"id":"namespace_digesthighlight","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestHighlight.target","file":"api/mail/digest.ts","doc":"What they did it on, absent for a follow of the reader or the chat. Its url is null once it is deleted, and the title then shows unlinked.","url":"./api/mail/digest.ts/~/DigestHighlight.target.html","deprecated":false},{"id":"namespace_digesthighlight","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestHighlight.target.title","file":"api/mail/digest.ts","doc":"","url":"./api/mail/digest.ts/~/DigestHighlight.target.title.html","deprecated":false},{"id":"namespace_digesthighlight","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestHighlight.target.url","file":"api/mail/digest.ts","doc":"","url":"./api/mail/digest.ts/~/DigestHighlight.target.url.html","deprecated":false},{"id":"namespace_digesthighlight","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestHighlight.quote","file":"api/mail/digest.ts","doc":"The comment or message, flattened and shortened.","url":"./api/mail/digest.ts/~/DigestHighlight.quote.html","deprecated":false},{"id":"namespace_digesthighlight","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestHighlight.at","file":"api/mail/digest.ts","doc":"","url":"./api/mail/digest.ts/~/DigestHighlight.at.html","deprecated":false},{"id":"namespace_digestcontent","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"DigestContent","file":"api/mail/digest.ts","doc":"Passed to renderDigestEmail by digest-service.ts. Each section is null when it has nothing to show, and is left out; the service sends nothing when all of them are.","url":"./api/mail/digest.ts/~/DigestContent.html","deprecated":false},{"id":"namespace_digestcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestContent.cadence","file":"api/mail/digest.ts","doc":"","url":"./api/mail/digest.ts/~/DigestContent.cadence.html","deprecated":false},{"id":"namespace_digestcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestContent.from","file":"api/mail/digest.ts","doc":"The period covered, from from to to.","url":"./api/mail/digest.ts/~/DigestContent.from.html","deprecated":false},{"id":"namespace_digestcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestContent.to","file":"api/mail/digest.ts","doc":"","url":"./api/mail/digest.ts/~/DigestContent.to.html","deprecated":false},{"id":"namespace_digestcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestContent.reader","file":"api/mail/digest.ts","doc":"","url":"./api/mail/digest.ts/~/DigestContent.reader.html","deprecated":false},{"id":"namespace_digestcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestContent.activity","file":"api/mail/digest.ts","doc":"Weekly only.","url":"./api/mail/digest.ts/~/DigestContent.activity.html","deprecated":false},{"id":"namespace_digestcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestContent.network","file":"api/mail/digest.ts","doc":"Weekly only.","url":"./api/mail/digest.ts/~/DigestContent.network.html","deprecated":false},{"id":"namespace_digestcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestContent.top","file":"api/mail/digest.ts","doc":"","url":"./api/mail/digest.ts/~/DigestContent.top.html","deprecated":false},{"id":"namespace_digestcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestContent.community","file":"api/mail/digest.ts","doc":"","url":"./api/mail/digest.ts/~/DigestContent.community.html","deprecated":false},{"id":"namespace_digestcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestContent.links","file":"api/mail/digest.ts","doc":"","url":"./api/mail/digest.ts/~/DigestContent.links.html","deprecated":false},{"id":"namespace_digestcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestContent.links.notifications","file":"api/mail/digest.ts","doc":"","url":"./api/mail/digest.ts/~/DigestContent.links.notifications.html","deprecated":false},{"id":"namespace_digestcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestContent.links.followed","file":"api/mail/digest.ts","doc":"","url":"./api/mail/digest.ts/~/DigestContent.links.followed.html","deprecated":false},{"id":"namespace_digestcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestContent.links.chat","file":"api/mail/digest.ts","doc":"","url":"./api/mail/digest.ts/~/DigestContent.links.chat.html","deprecated":false},{"id":"namespace_digestcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestContent.links.community","file":"api/mail/digest.ts","doc":"The community page's view of the cadence's period.","url":"./api/mail/digest.ts/~/DigestContent.links.community.html","deprecated":false},{"id":"namespace_digestcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestContent.links.settings","file":"api/mail/digest.ts","doc":"","url":"./api/mail/digest.ts/~/DigestContent.links.settings.html","deprecated":false},{"id":"namespace_digestcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DigestContent.links.unsubscribe","file":"api/mail/digest.ts","doc":"The one-click page that turns this cadence off.","url":"./api/mail/digest.ts/~/DigestContent.links.unsubscribe.html","deprecated":false},{"id":"namespace_renderdigestemail","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"renderDigestEmail","file":"api/mail/digest.ts","doc":"Returns the digest content describes, written as Markdown and drawn in look, with its subject and hidden preheader.","url":"./api/mail/digest.ts/~/renderDigestEmail.html","deprecated":false},{"id":"namespace_i18n","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"i18n","file":"api/mail/i18n.ts","doc":"Translates the emails' messages, in EMAIL_LOCALE. Every catalog is loaded, so a test can activate another language.","url":"./api/mail/i18n.ts/~/i18n.html","deprecated":false},{"id":"namespace_renderedemail","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"RenderedEmail","file":"api/mail/layout.ts","doc":"Returned by each template to its caller, which hands it to sendEmail with a recipient.","url":"./api/mail/layout.ts/~/RenderedEmail.html","deprecated":false},{"id":"namespace_renderedemail","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RenderedEmail.subject","file":"api/mail/layout.ts","doc":"","url":"./api/mail/layout.ts/~/RenderedEmail.subject.html","deprecated":false},{"id":"namespace_renderedemail","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RenderedEmail.html","file":"api/mail/layout.ts","doc":"","url":"./api/mail/layout.ts/~/RenderedEmail.html.html","deprecated":false},{"id":"namespace_renderedemail","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RenderedEmail.text","file":"api/mail/layout.ts","doc":"The plain-text part, for clients that show no HTML. It is Markdown, so it reads as text and renders as the email's outline.","url":"./api/mail/layout.ts/~/RenderedEmail.text.html","deprecated":false},{"id":"namespace_emaillook","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"EmailLook","file":"api/mail/layout.ts","doc":"Passed to EmailKit, made by lookOf: the instance's style for the emails that aren't a user's own, their settings for a digest.","url":"./api/mail/layout.ts/~/EmailLook.html","deprecated":false},{"id":"namespace_emaillook","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailLook.style","file":"api/mail/layout.ts","doc":"","url":"./api/mail/layout.ts/~/EmailLook.style.html","deprecated":false},{"id":"namespace_emaillook","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailLook.scheme","file":"api/mail/layout.ts","doc":"","url":"./api/mail/layout.ts/~/EmailLook.scheme.html","deprecated":false},{"id":"namespace_lookof","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"lookOf","file":"api/mail/layout.ts","doc":"Returns the look of a reader's settings. An unset style is the instance's, as on the site, and an unset scheme the system's; with no settings at all, as for the welcome and reset emails, both are.","url":"./api/mail/layout.ts/~/lookOf.html","deprecated":false},{"id":"namespace_paletterole","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"PaletteRole","file":"api/mail/layout.ts","doc":"Names a color of an EmailPalette, as EmailKit.paint takes it, so that the dark block can recolor the element by the same name.","url":"./api/mail/layout.ts/~/PaletteRole.html","deprecated":false},{"id":"namespace_esc","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"esc","file":"api/mail/layout.ts","doc":"Escapes value for HTML text and attributes. Everything users wrote (names, titles, quotes) goes through it, since none of it may become markup.","url":"./api/mail/layout.ts/~/esc.html","deprecated":false},{"id":"namespace_escmd","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"escMd","file":"api/mail/layout.ts","doc":"Escapes value for Markdown, so that user text in a plain-text part (a title with * or [, say) stays text.","url":"./api/mail/layout.ts/~/escMd.html","deprecated":false},{"id":"namespace_mdlink","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"mdLink","file":"api/mail/layout.ts","doc":"Returns a Markdown link to url labelled with text, escaped.","url":"./api/mail/layout.ts/~/mdLink.html","deprecated":false},{"id":"namespace_emailkit","kind":[{"char":"c","kind":"Class","title":"Class"}],"name":"EmailKit","file":"api/mail/layout.ts","doc":"Draws an email in one EmailLook. A template writes the email as Markdown and hands it to EmailKit.render, which draws each block in the style. The block methods return HTML: text passed to them must already be escaped with esc.","url":"./api/mail/layout.ts/~/EmailKit.html","deprecated":false},{"id":"namespace_emailkit","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"EmailKit.prototype.fs","file":"api/mail/layout.ts","doc":"Returns px, scaled for the style, as a CSS length.","url":"./api/mail/layout.ts/~/EmailKit.prototype.fs.html","deprecated":false},{"id":"namespace_emailkit","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"EmailKit.prototype.paint","file":"api/mail/layout.ts","doc":"Returns the class and style attributes of an element colored by roles: fg for its text, bg for its fill, bd for its border. The classes let the dark block recolor it; css is the rest of its style.","url":"./api/mail/layout.ts/~/EmailKit.prototype.paint.html","deprecated":false},{"id":"namespace_emailkit","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"EmailKit.prototype.link","file":"api/mail/layout.ts","doc":"Returns a link to href around html, in the link color.","url":"./api/mail/layout.ts/~/EmailKit.prototype.link.html","deprecated":false},{"id":"namespace_emailkit","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"EmailKit.prototype.heading","file":"api/mail/layout.ts","doc":"Returns the email's heading, in the style's title type.","url":"./api/mail/layout.ts/~/EmailKit.prototype.heading.html","deprecated":false},{"id":"namespace_emailkit","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"EmailKit.prototype.para","file":"api/mail/layout.ts","doc":"Returns a paragraph. css adds to or overrides its style.","url":"./api/mail/layout.ts/~/EmailKit.prototype.para.html","deprecated":false},{"id":"namespace_emailkit","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"EmailKit.prototype.note","file":"api/mail/layout.ts","doc":"Returns a smaller paragraph in the muted color.","url":"./api/mail/layout.ts/~/EmailKit.prototype.note.html","deprecated":false},{"id":"namespace_emailkit","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"EmailKit.prototype.button","file":"api/mail/layout.ts","doc":"Returns a button linking to href.","url":"./api/mail/layout.ts/~/EmailKit.prototype.button.html","deprecated":false},{"id":"namespace_emailkit","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"EmailKit.prototype.pill","file":"api/mail/layout.ts","doc":"Returns a small uppercase pill, as on one's own dump in a list.","url":"./api/mail/layout.ts/~/EmailKit.prototype.pill.html","deprecated":false},{"id":"namespace_emailkit","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"EmailKit.prototype.image","file":"api/mail/layout.ts","doc":"Returns an image block, rounded as the style rounds images.","url":"./api/mail/layout.ts/~/EmailKit.prototype.image.html","deprecated":false},{"id":"namespace_emailkit","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"EmailKit.prototype.subhead","file":"api/mail/layout.ts","doc":"Returns a small bold heading inside a section.","url":"./api/mail/layout.ts/~/EmailKit.prototype.subhead.html","deprecated":false},{"id":"namespace_emailkit","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"EmailKit.prototype.section","file":"api/mail/layout.ts","doc":"Returns a section of the card: a divider in the style's rule (none before the first), an uppercase title in the accent color, and html.","url":"./api/mail/layout.ts/~/EmailKit.prototype.section.html","deprecated":false},{"id":"namespace_emailkit","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"EmailKit.prototype.render","file":"api/mail/layout.ts","doc":"Returns the email written as markdown: the Markdown itself is the plain-text part, and its blocks, drawn in this kit's style, are the HTML. Each template writes its email once this way. The blocks map as follows.# Title is the heading; an *emphasised* paragraph above it, the eyebrow. Elsewhere an emphasised paragraph is a note.## Section starts a section, with its divider; ### Name a subhead.A link alone in a paragraph is a button, an image alone a wide image, and a fenced block a box for a raw link.A list item whose text starts with an image, then a link, is a row with that thumbnail and the link as its title; what follows is its detail, and an emphasised word right after the link a pill. Other items are sentences, where emphasis marks the date. A numbered list ranks its rows, and a quote under an item is set as one.A bold number is a figure.What follows the last --- is the footer.","url":"./api/mail/layout.ts/~/EmailKit.prototype.render.html","deprecated":false},{"id":"namespace_emailkit","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"EmailKit.prototype.inline","file":"api/mail/layout.ts","doc":"","url":"./api/mail/layout.ts/~/EmailKit.prototype.inline.html","deprecated":false},{"id":"namespace_emailkit","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"EmailKit.prototype.blocks","file":"api/mail/layout.ts","doc":"Draws the body's blocks, gathering each ## section with its content.","url":"./api/mail/layout.ts/~/EmailKit.prototype.blocks.html","deprecated":false},{"id":"namespace_emailkit","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"EmailKit.prototype.list","file":"api/mail/layout.ts","doc":"Draws a list as rows, ranked when it is numbered.","url":"./api/mail/layout.ts/~/EmailKit.prototype.list.html","deprecated":false},{"id":"namespace_emailkit","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"EmailKit.prototype.eyebrow","file":"api/mail/layout.ts","doc":"Returns the small uppercase line above the heading.","url":"./api/mail/layout.ts/~/EmailKit.prototype.eyebrow.html","deprecated":false},{"id":"namespace_emailkit","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"EmailKit.prototype.quote","file":"api/mail/layout.ts","doc":"Returns a quoted comment or message.","url":"./api/mail/layout.ts/~/EmailKit.prototype.quote.html","deprecated":false},{"id":"namespace_emailkit","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"EmailKit.prototype.linkBox","file":"api/mail/layout.ts","doc":"Returns a raw link set in a box, for clients that break buttons.","url":"./api/mail/layout.ts/~/EmailKit.prototype.linkBox.html","deprecated":false},{"id":"namespace_emailkit","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"EmailKit.prototype.document","file":"api/mail/layout.ts","doc":"Returns the whole HTML document: the brand, the card holding body, and the footer. preheader is the hidden first line inboxes show beside the subject.","url":"./api/mail/layout.ts/~/EmailKit.prototype.document.html","deprecated":false},{"id":"namespace_emailkit","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"EmailKit.prototype.darkCss","file":"api/mail/layout.ts","doc":"Returns the CSS that recolors every painted element in dark mode, or nothing off the \"auto\" scheme.","url":"./api/mail/layout.ts/~/EmailKit.prototype.darkCss.html","deprecated":false},{"id":"namespace_emailkit","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailKit.prototype.style","file":"api/mail/layout.ts","doc":"The style being drawn.","url":"./api/mail/layout.ts/~/EmailKit.prototype.style.html","deprecated":false},{"id":"namespace_emailkit","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailKit.prototype.palette","file":"api/mail/layout.ts","doc":"The palette inlined into the HTML.","url":"./api/mail/layout.ts/~/EmailKit.prototype.palette.html","deprecated":false},{"id":"namespace_emailkit","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailKit.prototype.darkPalette","file":"api/mail/layout.ts","doc":"The palette that replaces it in dark mode, on the \"auto\" scheme only.","url":"./api/mail/layout.ts/~/EmailKit.prototype.darkPalette.html","deprecated":false},{"id":"namespace_emailkit","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailKit.prototype.font","file":"api/mail/layout.ts","doc":"The font stack, for templates that set their own blocks.","url":"./api/mail/layout.ts/~/EmailKit.prototype.font.html","deprecated":false},{"id":"namespace_emailkit","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailKit.prototype.mode","file":"api/mail/layout.ts","doc":"How inline draws emphasis and links, by where they sit.","url":"./api/mail/layout.ts/~/EmailKit.prototype.mode.html","deprecated":false},{"id":"namespace_emailkit","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailKit.prototype.marked","file":"api/mail/layout.ts","doc":"Draws Markdown's inline tokens with the kit's colors.","url":"./api/mail/layout.ts/~/EmailKit.prototype.marked.html","deprecated":false},{"id":"namespace_renderpasswordresetemail","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"renderPasswordResetEmail","file":"api/mail/password-reset.ts","doc":"Returns the reset email of username, whose button opens resetUrl. The link stays usable for hours, which the email states.","url":"./api/mail/password-reset.ts/~/renderPasswordResetEmail.html","deprecated":false},{"id":"namespace_emailpalette","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"EmailPalette","file":"api/mail/styles.ts","doc":"The colors of one style in one scheme, by role, each read from a token of its theme. The optional ones carry a style's particular touches.","url":"./api/mail/styles.ts/~/EmailPalette.html","deprecated":false},{"id":"namespace_emailpalette","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailPalette.outer","file":"api/mail/styles.ts","doc":"The page around the card (--color-bg).","url":"./api/mail/styles.ts/~/EmailPalette.outer.html","deprecated":false},{"id":"namespace_emailpalette","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailPalette.card","file":"api/mail/styles.ts","doc":"The card holding the content (--color-surface).","url":"./api/mail/styles.ts/~/EmailPalette.card.html","deprecated":false},{"id":"namespace_emailpalette","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailPalette.text","file":"api/mail/styles.ts","doc":"--color-text.","url":"./api/mail/styles.ts/~/EmailPalette.text.html","deprecated":false},{"id":"namespace_emailpalette","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailPalette.sec","file":"api/mail/styles.ts","doc":"--color-text-secondary.","url":"./api/mail/styles.ts/~/EmailPalette.sec.html","deprecated":false},{"id":"namespace_emailpalette","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailPalette.muted","file":"api/mail/styles.ts","doc":"--color-text-muted.","url":"./api/mail/styles.ts/~/EmailPalette.muted.html","deprecated":false},{"id":"namespace_emailpalette","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailPalette.accent","file":"api/mail/styles.ts","doc":"Section titles, ranks and button fills (--color-accent).","url":"./api/mail/styles.ts/~/EmailPalette.accent.html","deprecated":false},{"id":"namespace_emailpalette","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailPalette.link","file":"api/mail/styles.ts","doc":"--color-link.","url":"./api/mail/styles.ts/~/EmailPalette.link.html","deprecated":false},{"id":"namespace_emailpalette","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailPalette.onAccent","file":"api/mail/styles.ts","doc":"Text on an accent fill (--color-on-accent).","url":"./api/mail/styles.ts/~/EmailPalette.onAccent.html","deprecated":false},{"id":"namespace_emailpalette","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailPalette.rule","file":"api/mail/styles.ts","doc":"Dividers and hairlines (--color-border).","url":"./api/mail/styles.ts/~/EmailPalette.rule.html","deprecated":false},{"id":"namespace_emailpalette","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailPalette.soft","file":"api/mail/styles.ts","doc":"Pills and the reset link's box, as the site's badges (--color-badge-bg).","url":"./api/mail/styles.ts/~/EmailPalette.soft.html","deprecated":false},{"id":"namespace_emailpalette","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailPalette.quote","file":"api/mail/styles.ts","doc":"Quoted comments and messages (--color-text-secondary unless set).","url":"./api/mail/styles.ts/~/EmailPalette.quote.html","deprecated":false},{"id":"namespace_emailpalette","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailPalette.date","file":"api/mail/styles.ts","doc":"Kanagawa's fujiGray dates; others use muted.","url":"./api/mail/styles.ts/~/EmailPalette.date.html","deprecated":false},{"id":"namespace_emailpalette","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailPalette.brand","file":"api/mail/styles.ts","doc":"Kanagawa's oniViolet wordmark; others use text.","url":"./api/mail/styles.ts/~/EmailPalette.brand.html","deprecated":false},{"id":"namespace_emailpalette","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailPalette.border","file":"api/mail/styles.ts","doc":"GeoCities' ridged border.","url":"./api/mail/styles.ts/~/EmailPalette.border.html","deprecated":false},{"id":"namespace_emailpalette","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailPalette.shadow","file":"api/mail/styles.ts","doc":"Melange's warm card shadow, translucent.","url":"./api/mail/styles.ts/~/EmailPalette.shadow.html","deprecated":false},{"id":"namespace_emailpalette","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailPalette.gradient","file":"api/mail/styles.ts","doc":"The colors of GeoCities' rainbow or Melange's spice, left to right.","url":"./api/mail/styles.ts/~/EmailPalette.gradient.html","deprecated":false},{"id":"namespace_emailstyle","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"EmailStyle","file":"api/mail/styles.ts","doc":"How a style draws an email. layout.ts builds every block from it, so adding a style to shared/theme.ts means adding its Recipe here.","url":"./api/mail/styles.ts/~/EmailStyle.html","deprecated":false},{"id":"namespace_emailstyle","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailStyle.font","file":"api/mail/styles.ts","doc":"The theme's font stack (--font-body). Its first family is a web font only Apple's mail apps load, through webFont; other clients fall back along the stack.","url":"./api/mail/styles.ts/~/EmailStyle.font.html","deprecated":false},{"id":"namespace_emailstyle","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailStyle.webFont","file":"api/mail/styles.ts","doc":"The Google Fonts family parameter of the web font, if it is one.","url":"./api/mail/styles.ts/~/EmailStyle.webFont.html","deprecated":false},{"id":"namespace_emailstyle","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailStyle.scale","file":"api/mail/styles.ts","doc":"Multiplies every font size: Times sets its serif larger, Kanagawa its monospace smaller.","url":"./api/mail/styles.ts/~/EmailStyle.scale.html","deprecated":false},{"id":"namespace_emailstyle","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailStyle.radius","file":"api/mail/styles.ts","doc":"Corner radii, in pixels: the card's as the site's cards (--radius-xl), the images' as its thumbnails (--radius-md), the buttons' as its buttons (--radius-lg), the pills' as its badges (--radius-sm). The avatars' is the email's own, since the site rounds them with a literal 50% that some styles square.","url":"./api/mail/styles.ts/~/EmailStyle.radius.html","deprecated":false},{"id":"namespace_emailstyle","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailStyle.radius.card","file":"api/mail/styles.ts","doc":"","url":"./api/mail/styles.ts/~/EmailStyle.radius.card.html","deprecated":false},{"id":"namespace_emailstyle","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailStyle.radius.img","file":"api/mail/styles.ts","doc":"","url":"./api/mail/styles.ts/~/EmailStyle.radius.img.html","deprecated":false},{"id":"namespace_emailstyle","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailStyle.radius.btn","file":"api/mail/styles.ts","doc":"","url":"./api/mail/styles.ts/~/EmailStyle.radius.btn.html","deprecated":false},{"id":"namespace_emailstyle","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailStyle.radius.pill","file":"api/mail/styles.ts","doc":"","url":"./api/mail/styles.ts/~/EmailStyle.radius.pill.html","deprecated":false},{"id":"namespace_emailstyle","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailStyle.radius.avatar","file":"api/mail/styles.ts","doc":"","url":"./api/mail/styles.ts/~/EmailStyle.radius.avatar.html","deprecated":false},{"id":"namespace_emailstyle","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailStyle.title","file":"api/mail/styles.ts","doc":"The heading: its size in pixels, weight, and Brutalist's uppercase and spacing.","url":"./api/mail/styles.ts/~/EmailStyle.title.html","deprecated":false},{"id":"namespace_emailstyle","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailStyle.title.size","file":"api/mail/styles.ts","doc":"","url":"./api/mail/styles.ts/~/EmailStyle.title.size.html","deprecated":false},{"id":"namespace_emailstyle","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailStyle.title.weight","file":"api/mail/styles.ts","doc":"","url":"./api/mail/styles.ts/~/EmailStyle.title.weight.html","deprecated":false},{"id":"namespace_emailstyle","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailStyle.title.upper","file":"api/mail/styles.ts","doc":"","url":"./api/mail/styles.ts/~/EmailStyle.title.upper.html","deprecated":false},{"id":"namespace_emailstyle","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailStyle.title.spacing","file":"api/mail/styles.ts","doc":"","url":"./api/mail/styles.ts/~/EmailStyle.title.spacing.html","deprecated":false},{"id":"namespace_emailstyle","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailStyle.title.accent","file":"api/mail/styles.ts","doc":"","url":"./api/mail/styles.ts/~/EmailStyle.title.accent.html","deprecated":false},{"id":"namespace_emailstyle","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailStyle.heavy","file":"api/mail/styles.ts","doc":"The weight of titles of items, figures and names.","url":"./api/mail/styles.ts/~/EmailStyle.heavy.html","deprecated":false},{"id":"namespace_emailstyle","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailStyle.frame","file":"api/mail/styles.ts","doc":"How the card stands out from the page.","url":"./api/mail/styles.ts/~/EmailStyle.frame.html","deprecated":false},{"id":"namespace_emailstyle","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailStyle.rule","file":"api/mail/styles.ts","doc":"The divider between sections; \"gradient\" draws the palette's.","url":"./api/mail/styles.ts/~/EmailStyle.rule.html","deprecated":false},{"id":"namespace_emailstyle","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailStyle.bar","file":"api/mail/styles.ts","doc":"Draws the palette's gradient as a bar along the card's top.","url":"./api/mail/styles.ts/~/EmailStyle.bar.html","deprecated":false},{"id":"namespace_emailstyle","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailStyle.linkUnderline","file":"api/mail/styles.ts","doc":"Underlines links, for styles whose links are the color of the text.","url":"./api/mail/styles.ts/~/EmailStyle.linkUnderline.html","deprecated":false},{"id":"namespace_emailstyle","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailStyle.light","file":"api/mail/styles.ts","doc":"","url":"./api/mail/styles.ts/~/EmailStyle.light.html","deprecated":false},{"id":"namespace_emailstyle","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmailStyle.dark","file":"api/mail/styles.ts","doc":"","url":"./api/mail/styles.ts/~/EmailStyle.dark.html","deprecated":false},{"id":"namespace_email_styles","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"EMAIL_STYLES","file":"api/mail/styles.ts","doc":"Every style's email look, keyed by its name, read once at load.","url":"./api/mail/styles.ts/~/EMAIL_STYLES.html","deprecated":false},{"id":"namespace_scheme","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"Scheme","file":"api/mail/theme-tokens.ts","doc":"A scheme a token is resolved for. \"auto\" is drawn from both.","url":"./api/mail/theme-tokens.ts/~/Scheme.html","deprecated":false},{"id":"namespace_themetokens","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ThemeTokens","file":"api/mail/theme-tokens.ts","doc":"Returned by readTokens: the tokens of one style in one scheme, read as the kind of value each is.","url":"./api/mail/theme-tokens.ts/~/ThemeTokens.html","deprecated":false},{"id":"namespace_themetokens","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"ThemeTokens.value","file":"api/mail/theme-tokens.ts","doc":"Returns the resolved value of token, or throws when it isn't set.","url":"./api/mail/theme-tokens.ts/~/ThemeTokens.value.html","deprecated":false},{"id":"namespace_themetokens","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"ThemeTokens.color","file":"api/mail/theme-tokens.ts","doc":"Returns the color of token as #rrggbb. A translucent one is laid over over (another token) first, as it shows on the site; without over it stays rgba(), as a shadow's must.","url":"./api/mail/theme-tokens.ts/~/ThemeTokens.color.html","deprecated":false},{"id":"namespace_themetokens","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"ThemeTokens.stops","file":"api/mail/theme-tokens.ts","doc":"Returns the colors of the gradient token, in order, without positions.","url":"./api/mail/theme-tokens.ts/~/ThemeTokens.stops.html","deprecated":false},{"id":"namespace_themetokens","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"ThemeTokens.font","file":"api/mail/theme-tokens.ts","doc":"Returns the font stack of token, single-quoted for a style attribute. A family the site bundles as \"X Variable\" is named \"X\", as a mail client or Google Fonts knows it.","url":"./api/mail/theme-tokens.ts/~/ThemeTokens.font.html","deprecated":false},{"id":"namespace_themetokens","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"ThemeTokens.px","file":"api/mail/theme-tokens.ts","doc":"Returns the length of token in pixels.","url":"./api/mail/theme-tokens.ts/~/ThemeTokens.px.html","deprecated":false},{"id":"namespace_readtokens","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"readTokens","file":"api/mail/theme-tokens.ts","doc":"Returns the tokens of style in scheme, read from the site's stylesheets at the time of the call. styles.ts reads each style once, at load.","url":"./api/mail/theme-tokens.ts/~/readTokens.html","deprecated":false},{"id":"namespace_renderwelcomeemail","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"renderWelcomeEmail","file":"api/mail/welcome.ts","doc":"Returns the welcome email of username. The instance's body has {{username}} and {{site_name}} filled in; raw HTML in it passes through, since it comes from whoever runs the instance, never from a user.","url":"./api/mail/welcome.ts/~/renderWelcomeEmail.html","deprecated":false},{"id":"namespace_app","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"app","file":"api/main.ts","doc":"The whole server, exported so the tests' helpers can send it requests without listening.","url":"./api/main.ts/~/app.html","deprecated":false},{"id":"namespace_authstate","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"AuthState","file":"api/middleware/auth.ts","doc":"Set on ctx.state by authMiddleware for the handlers after it. user carries the caller's live role, not the one in their token.","url":"./api/middleware/auth.ts/~/AuthState.html","deprecated":false},{"id":"namespace_authstate","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AuthState.user","file":"api/middleware/auth.ts","doc":"","url":"./api/middleware/auth.ts/~/AuthState.user.html","deprecated":false},{"id":"namespace_authcontext","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"AuthContext","file":"api/middleware/auth.ts","doc":"The context type of a handler behind authMiddleware. Pass the route path, as in AuthContext<\"/:key/role\">, to keep ctx.params typed.","url":"./api/middleware/auth.ts/~/AuthContext.html","deprecated":false},{"id":"namespace_authmiddleware","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"authMiddleware","file":"api/middleware/auth.ts","doc":"Requires a valid session token in the Authorization header, and puts its payload in ctx.state.user for the rest of the route.","url":"./api/middleware/auth.ts/~/authMiddleware.html","deprecated":false},{"id":"namespace_requirepermission","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"requirePermission","file":"api/middleware/auth.ts","doc":"Returns a middleware that requires the caller to hold permission. It must run after authMiddleware, as in router.patch(path, authMiddleware, requirePermission(\"user:manage\"), …). The returned middleware throws an APIException (403) when the caller lacks the permission.","url":"./api/middleware/auth.ts/~/requirePermission.html","deprecated":false},{"id":"namespace_compressmiddleware","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"compressMiddleware","file":"api/middleware/compress.ts","doc":"Sends the response's JSON or text compressed, in brotli or gzip as the request accepts, when it is at least MIN_BYTES long. A response already encoded, a HEAD, and one marked no-transform go out as they are.","url":"./api/middleware/compress.ts/~/compressMiddleware.html","deprecated":false},{"id":"namespace_errormiddleware","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"errorMiddleware","file":"api/middleware/error.ts","doc":"Answers an APIException with its status, code and message. Anything else is logged with its stack and answered with a 500 SERVER_ERROR whose message gives nothing away.","url":"./api/middleware/error.ts/~/errorMiddleware.html","deprecated":false},{"id":"namespace_ogmiddleware","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"ogMiddleware","file":"api/middleware/og.ts","doc":"Serves index.html with the tags of the dump, user or public playlist a path names (parsePagePath), and passes the request on when it names none that exists or the visitor may see. A path naming one by a former name, a user's or a slug, or in another case, gets a 301 to its current path. The page's URL is on FRONTEND_URL and the images' on PUBLIC_URL, not on the request's origin, which a reverse proxy may have rewritten to an internal host or plain http.","url":"./api/middleware/og.ts/~/ogMiddleware.html","deprecated":false},{"id":"namespace_authpayload","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"AuthPayload","file":"api/model/auth.ts","doc":"Signed into a session token by createJWT, and returned by authenticate to the auth middleware as ctx.state.user. By then role is the user's live role, while username is still the one at issue time.","url":"./api/model/auth.ts/~/AuthPayload.html","deprecated":false},{"id":"namespace_authpayload","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AuthPayload.userId","file":"api/model/auth.ts","doc":"","url":"./api/model/auth.ts/~/AuthPayload.userId.html","deprecated":false},{"id":"namespace_authpayload","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AuthPayload.username","file":"api/model/auth.ts","doc":"","url":"./api/model/auth.ts/~/AuthPayload.username.html","deprecated":false},{"id":"namespace_authpayload","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AuthPayload.role","file":"api/model/auth.ts","doc":"","url":"./api/model/auth.ts/~/AuthPayload.role.html","deprecated":false},{"id":"namespace_authpayload","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AuthPayload.exp","file":"api/model/auth.ts","doc":"Seconds since the epoch.","url":"./api/model/auth.ts/~/AuthPayload.exp.html","deprecated":false},{"id":"namespace_authpayload","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AuthPayload.iat","file":"api/model/auth.ts","doc":"Seconds since the epoch, compared with users.tokens_valid_after.","url":"./api/model/auth.ts/~/AuthPayload.iat.html","deprecated":false},{"id":"namespace_isauthpayload","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isAuthPayload","file":"api/model/auth.ts","doc":"Checks whether obj is an AuthPayload. A media or reset token's payload, which has a purpose, never is.","url":"./api/model/auth.ts/~/isAuthPayload.html","deprecated":false},{"id":"namespace_passwordresetpayload","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PasswordResetPayload","file":"api/model/auth.ts","doc":"Signed into a reset link's token by createPasswordResetToken, and returned by verifyPasswordResetToken to resetPassword.","url":"./api/model/auth.ts/~/PasswordResetPayload.html","deprecated":false},{"id":"namespace_passwordresetpayload","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PasswordResetPayload.purpose","file":"api/model/auth.ts","doc":"","url":"./api/model/auth.ts/~/PasswordResetPayload.purpose.html","deprecated":false},{"id":"namespace_passwordresetpayload","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PasswordResetPayload.userId","file":"api/model/auth.ts","doc":"","url":"./api/model/auth.ts/~/PasswordResetPayload.userId.html","deprecated":false},{"id":"namespace_passwordresetpayload","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PasswordResetPayload.exp","file":"api/model/auth.ts","doc":"Seconds since the epoch.","url":"./api/model/auth.ts/~/PasswordResetPayload.exp.html","deprecated":false},{"id":"namespace_ispasswordresetpayload","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isPasswordResetPayload","file":"api/model/auth.ts","doc":"Checks whether obj is a PasswordResetPayload. It doesn't check exp, which jwtVerify has already enforced.","url":"./api/model/auth.ts/~/isPasswordResetPayload.html","deprecated":false},{"id":"namespace_categoryrow","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CategoryRow","file":"api/model/category.ts","doc":"Returned by the category service's SELECTs on categories.","url":"./api/model/category.ts/~/CategoryRow.html","deprecated":false},{"id":"namespace_categoryrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CategoryRow.id","file":"api/model/category.ts","doc":"","url":"./api/model/category.ts/~/CategoryRow.id.html","deprecated":false},{"id":"namespace_categoryrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CategoryRow.kind","file":"api/model/category.ts","doc":"","url":"./api/model/category.ts/~/CategoryRow.kind.html","deprecated":false},{"id":"namespace_categoryrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CategoryRow.slug","file":"api/model/category.ts","doc":"","url":"./api/model/category.ts/~/CategoryRow.slug.html","deprecated":false},{"id":"namespace_categoryrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CategoryRow.name","file":"api/model/category.ts","doc":"","url":"./api/model/category.ts/~/CategoryRow.name.html","deprecated":false},{"id":"namespace_categoryrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CategoryRow.position","file":"api/model/category.ts","doc":"Sorts the categories, lowest first.","url":"./api/model/category.ts/~/CategoryRow.position.html","deprecated":false},{"id":"namespace_categoryrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CategoryRow.created_at","file":"api/model/category.ts","doc":"","url":"./api/model/category.ts/~/CategoryRow.created_at.html","deprecated":false},{"id":"namespace_categoryrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CategoryRow.updated_at","file":"api/model/category.ts","doc":"","url":"./api/model/category.ts/~/CategoryRow.updated_at.html","deprecated":false},{"id":"namespace_iscategoryrow","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isCategoryRow","file":"api/model/category.ts","doc":"Checks whether a row node:sqlite returned is a CategoryRow.","url":"./api/model/category.ts/~/isCategoryRow.html","deprecated":false},{"id":"namespace_categoryrowtoapi","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"categoryRowToApi","file":"api/model/category.ts","doc":"Converts row to the Category the category routes send.","url":"./api/model/category.ts/~/categoryRowToApi.html","deprecated":false},{"id":"namespace_chatmessagerow","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ChatMessageRow","file":"api/model/chat.ts","doc":"Returned by chat-service's query, which joins each message to its author and to the message it replies to. reply_to_id is kept when the message it points to is deleted, while reply_to_author and reply_to_body then read null.","url":"./api/model/chat.ts/~/ChatMessageRow.html","deprecated":false},{"id":"namespace_chatmessagerow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageRow.id","file":"api/model/chat.ts","doc":"","url":"./api/model/chat.ts/~/ChatMessageRow.id.html","deprecated":false},{"id":"namespace_chatmessagerow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageRow.user_id","file":"api/model/chat.ts","doc":"","url":"./api/model/chat.ts/~/ChatMessageRow.user_id.html","deprecated":false},{"id":"namespace_chatmessagerow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageRow.body","file":"api/model/chat.ts","doc":"","url":"./api/model/chat.ts/~/ChatMessageRow.body.html","deprecated":false},{"id":"namespace_chatmessagerow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageRow.created_at","file":"api/model/chat.ts","doc":"","url":"./api/model/chat.ts/~/ChatMessageRow.created_at.html","deprecated":false},{"id":"namespace_chatmessagerow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageRow.updated_at","file":"api/model/chat.ts","doc":"","url":"./api/model/chat.ts/~/ChatMessageRow.updated_at.html","deprecated":false},{"id":"namespace_chatmessagerow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageRow.author_username","file":"api/model/chat.ts","doc":"","url":"./api/model/chat.ts/~/ChatMessageRow.author_username.html","deprecated":false},{"id":"namespace_chatmessagerow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageRow.author_avatar_mime","file":"api/model/chat.ts","doc":"","url":"./api/model/chat.ts/~/ChatMessageRow.author_avatar_mime.html","deprecated":false},{"id":"namespace_chatmessagerow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageRow.reply_to_id","file":"api/model/chat.ts","doc":"","url":"./api/model/chat.ts/~/ChatMessageRow.reply_to_id.html","deprecated":false},{"id":"namespace_chatmessagerow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageRow.reply_to_author","file":"api/model/chat.ts","doc":"","url":"./api/model/chat.ts/~/ChatMessageRow.reply_to_author.html","deprecated":false},{"id":"namespace_chatmessagerow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageRow.reply_to_body","file":"api/model/chat.ts","doc":"Cut to chat-service's REPLY_SNIPPET_LEN characters.","url":"./api/model/chat.ts/~/ChatMessageRow.reply_to_body.html","deprecated":false},{"id":"namespace_chatmessagerow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageRow.mentions_everyone","file":"api/model/chat.ts","doc":"1 or 0.","url":"./api/model/chat.ts/~/ChatMessageRow.mentions_everyone.html","deprecated":false},{"id":"namespace_ischatmessagerow","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isChatMessageRow","file":"api/model/chat.ts","doc":"Checks whether obj, a row read by chat-service, is a ChatMessageRow.","url":"./api/model/chat.ts/~/isChatMessageRow.html","deprecated":false},{"id":"namespace_chatmessagerowtoapi","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"chatMessageRowToApi","file":"api/model/chat.ts","doc":"Converts a row to the ChatMessage that chat-service returns, turning its timestamps into Dates and its nulls into absent fields.","url":"./api/model/chat.ts/~/chatMessageRowToApi.html","deprecated":false},{"id":"namespace_commentrow","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CommentRow","file":"api/model/comment.ts","doc":"Returned by the comment service's SELECTs on comments, joined with users for the author_ columns.","url":"./api/model/comment.ts/~/CommentRow.html","deprecated":false},{"id":"namespace_commentrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentRow.id","file":"api/model/comment.ts","doc":"","url":"./api/model/comment.ts/~/CommentRow.id.html","deprecated":false},{"id":"namespace_commentrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentRow.dump_id","file":"api/model/comment.ts","doc":"","url":"./api/model/comment.ts/~/CommentRow.dump_id.html","deprecated":false},{"id":"namespace_commentrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentRow.user_id","file":"api/model/comment.ts","doc":"","url":"./api/model/comment.ts/~/CommentRow.user_id.html","deprecated":false},{"id":"namespace_commentrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentRow.parent_id","file":"api/model/comment.ts","doc":"It is null on a top-level comment.","url":"./api/model/comment.ts/~/CommentRow.parent_id.html","deprecated":false},{"id":"namespace_commentrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentRow.body","file":"api/model/comment.ts","doc":"","url":"./api/model/comment.ts/~/CommentRow.body.html","deprecated":false},{"id":"namespace_commentrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentRow.created_at","file":"api/model/comment.ts","doc":"","url":"./api/model/comment.ts/~/CommentRow.created_at.html","deprecated":false},{"id":"namespace_commentrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentRow.updated_at","file":"api/model/comment.ts","doc":"","url":"./api/model/comment.ts/~/CommentRow.updated_at.html","deprecated":false},{"id":"namespace_commentrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentRow.deleted","file":"api/model/comment.ts","doc":"1 once deleted. The body is emptied but the row stays, so its replies keep their place in the thread.","url":"./api/model/comment.ts/~/CommentRow.deleted.html","deprecated":false},{"id":"namespace_commentrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentRow.like_count","file":"api/model/comment.ts","doc":"","url":"./api/model/comment.ts/~/CommentRow.like_count.html","deprecated":false},{"id":"namespace_commentrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentRow.author_username","file":"api/model/comment.ts","doc":"","url":"./api/model/comment.ts/~/CommentRow.author_username.html","deprecated":false},{"id":"namespace_commentrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentRow.author_avatar_mime","file":"api/model/comment.ts","doc":"","url":"./api/model/comment.ts/~/CommentRow.author_avatar_mime.html","deprecated":false},{"id":"namespace_iscommentrow","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isCommentRow","file":"api/model/comment.ts","doc":"Checks whether a row node:sqlite returned is a CommentRow.","url":"./api/model/comment.ts/~/isCommentRow.html","deprecated":false},{"id":"namespace_commentrowtoapi","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"commentRowToApi","file":"api/model/comment.ts","doc":"Converts row to the Comment the comment routes send and the WebSocket broadcasts.","url":"./api/model/comment.ts/~/commentRowToApi.html","deprecated":false},{"id":"namespace_dumprow","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"DumpRow","file":"api/model/dump.ts","doc":"Read from the dumps table with DUMP_SELECT_COLUMNS, or written back from a Dump by dumpApiToRow. It lacks url_canonical, which only the duplicate lookup reads.","url":"./api/model/dump.ts/~/DumpRow.html","deprecated":false},{"id":"namespace_dumprow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpRow.id","file":"api/model/dump.ts","doc":"","url":"./api/model/dump.ts/~/DumpRow.id.html","deprecated":false},{"id":"namespace_dumprow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpRow.kind","file":"api/model/dump.ts","doc":"","url":"./api/model/dump.ts/~/DumpRow.kind.html","deprecated":false},{"id":"namespace_dumprow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpRow.title","file":"api/model/dump.ts","doc":"","url":"./api/model/dump.ts/~/DumpRow.title.html","deprecated":false},{"id":"namespace_dumprow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpRow.comment","file":"api/model/dump.ts","doc":"","url":"./api/model/dump.ts/~/DumpRow.comment.html","deprecated":false},{"id":"namespace_dumprow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpRow.user_id","file":"api/model/dump.ts","doc":"","url":"./api/model/dump.ts/~/DumpRow.user_id.html","deprecated":false},{"id":"namespace_dumprow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpRow.created_at","file":"api/model/dump.ts","doc":"","url":"./api/model/dump.ts/~/DumpRow.created_at.html","deprecated":false},{"id":"namespace_dumprow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpRow.updated_at","file":"api/model/dump.ts","doc":"","url":"./api/model/dump.ts/~/DumpRow.updated_at.html","deprecated":false},{"id":"namespace_dumprow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpRow.slug","file":"api/model/dump.ts","doc":"Unique among its poster's dumps, and set on every row since 0021.","url":"./api/model/dump.ts/~/DumpRow.slug.html","deprecated":false},{"id":"namespace_dumprow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpRow.url","file":"api/model/dump.ts","doc":"The link as the poster submitted it.","url":"./api/model/dump.ts/~/DumpRow.url.html","deprecated":false},{"id":"namespace_dumprow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpRow.rich_content","file":"api/model/dump.ts","doc":"RichContent as JSON.","url":"./api/model/dump.ts/~/DumpRow.rich_content.html","deprecated":false},{"id":"namespace_dumprow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpRow.file_name","file":"api/model/dump.ts","doc":"","url":"./api/model/dump.ts/~/DumpRow.file_name.html","deprecated":false},{"id":"namespace_dumprow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpRow.file_mime","file":"api/model/dump.ts","doc":"","url":"./api/model/dump.ts/~/DumpRow.file_mime.html","deprecated":false},{"id":"namespace_dumprow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpRow.file_size","file":"api/model/dump.ts","doc":"","url":"./api/model/dump.ts/~/DumpRow.file_size.html","deprecated":false},{"id":"namespace_dumprow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpRow.vote_count","file":"api/model/dump.ts","doc":"","url":"./api/model/dump.ts/~/DumpRow.vote_count.html","deprecated":false},{"id":"namespace_dumprow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpRow.comment_count","file":"api/model/dump.ts","doc":"Computed by a subquery, which counts the comments that aren't deleted.","url":"./api/model/dump.ts/~/DumpRow.comment_count.html","deprecated":false},{"id":"namespace_dumprow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpRow.owner_username","file":"api/model/dump.ts","doc":"The poster's current name, computed by a subquery.","url":"./api/model/dump.ts/~/DumpRow.owner_username.html","deprecated":false},{"id":"namespace_dumprow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpRow.is_private","file":"api/model/dump.ts","doc":"","url":"./api/model/dump.ts/~/DumpRow.is_private.html","deprecated":false},{"id":"namespace_dumprow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpRow.custom_thumbnail_mime","file":"api/model/dump.ts","doc":"","url":"./api/model/dump.ts/~/DumpRow.custom_thumbnail_mime.html","deprecated":false},{"id":"namespace_dump_columns","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"DUMP_COLUMNS","file":"api/model/dump.ts","doc":"Lists the stored columns of DumpRow. A column added to the table must be added here, to DumpRow and to isDumpRow.","url":"./api/model/dump.ts/~/DUMP_COLUMNS.html","deprecated":false},{"id":"namespace_dump_select_columns","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"DUMP_SELECT_COLUMNS","file":"api/model/dump.ts","doc":"Selects a whole DumpRow, the stored columns and the computed comment_count and owner_username.","url":"./api/model/dump.ts/~/DUMP_SELECT_COLUMNS.html","deprecated":false},{"id":"namespace_dump_select_columns_aliased","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"DUMP_SELECT_COLUMNS_ALIASED","file":"api/model/dump.ts","doc":"Selects a whole DumpRow in a query that aliases dumps as d to join it with other tables.","url":"./api/model/dump.ts/~/DUMP_SELECT_COLUMNS_ALIASED.html","deprecated":false},{"id":"namespace_isdumprow","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isDumpRow","file":"api/model/dump.ts","doc":"Checks whether obj, a row from a query, is a DumpRow. It checks each column's type, not that kind is url or file.","url":"./api/model/dump.ts/~/isDumpRow.html","deprecated":false},{"id":"namespace_dumprowtoapi","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"dumpRowToApi","file":"api/model/dump.ts","doc":"Converts a row to the API's Dump, parsing its preview's JSON. It leaves categoryIds out: the services add them with attachCategoryIds.","url":"./api/model/dump.ts/~/dumpRowToApi.html","deprecated":false},{"id":"namespace_dumpapitorow","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"dumpApiToRow","file":"api/model/dump.ts","doc":"Converts a Dump back to a row, for a service that writes an edited dump's columns.","url":"./api/model/dump.ts/~/dumpApiToRow.html","deprecated":false},{"id":"namespace_followrow","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"FollowRow","file":"api/model/follow.ts","doc":"Read by getFollowStatus. Exactly one of followed_user_id and followed_playlist_id is set, as the table's CHECK constraint requires.","url":"./api/model/follow.ts/~/FollowRow.html","deprecated":false},{"id":"namespace_followrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FollowRow.id","file":"api/model/follow.ts","doc":"","url":"./api/model/follow.ts/~/FollowRow.id.html","deprecated":false},{"id":"namespace_followrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FollowRow.follower_id","file":"api/model/follow.ts","doc":"","url":"./api/model/follow.ts/~/FollowRow.follower_id.html","deprecated":false},{"id":"namespace_followrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FollowRow.followed_user_id","file":"api/model/follow.ts","doc":"","url":"./api/model/follow.ts/~/FollowRow.followed_user_id.html","deprecated":false},{"id":"namespace_followrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FollowRow.followed_playlist_id","file":"api/model/follow.ts","doc":"","url":"./api/model/follow.ts/~/FollowRow.followed_playlist_id.html","deprecated":false},{"id":"namespace_followrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FollowRow.created_at","file":"api/model/follow.ts","doc":"","url":"./api/model/follow.ts/~/FollowRow.created_at.html","deprecated":false},{"id":"namespace_isfollowrow","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isFollowRow","file":"api/model/follow.ts","doc":"Checks whether obj, a row getFollowStatus selected, is a FollowRow.","url":"./api/model/follow.ts/~/isFollowRow.html","deprecated":false},{"id":"namespace_inviterow","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"InviteRow","file":"api/model/invite.ts","doc":"Stored by createInvite, and read back by validateInvite when the invite link is opened or used to sign up.","url":"./api/model/invite.ts/~/InviteRow.html","deprecated":false},{"id":"namespace_inviterow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InviteRow.token","file":"api/model/invite.ts","doc":"The random token the invite link carries, which is the primary key.","url":"./api/model/invite.ts/~/InviteRow.token.html","deprecated":false},{"id":"namespace_inviterow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InviteRow.inviter_id","file":"api/model/invite.ts","doc":"Becomes the new user's invited_by.","url":"./api/model/invite.ts/~/InviteRow.inviter_id.html","deprecated":false},{"id":"namespace_inviterow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InviteRow.used_at","file":"api/model/invite.ts","doc":"Set when an account is created with the invite.","url":"./api/model/invite.ts/~/InviteRow.used_at.html","deprecated":false},{"id":"namespace_inviterow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InviteRow.created_at","file":"api/model/invite.ts","doc":"Starts the 7-day window in which the invite works.","url":"./api/model/invite.ts/~/InviteRow.created_at.html","deprecated":false},{"id":"namespace_isinviterow","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isInviteRow","file":"api/model/invite.ts","doc":"Checks whether obj, a row validateInvite selected, is an InviteRow.","url":"./api/model/invite.ts/~/isInviteRow.html","deprecated":false},{"id":"namespace_notificationrow","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"NotificationRow","file":"api/model/notification.ts","doc":"Stored by the triggers of notification-service.ts, and read back by getNotificationsForUser.","url":"./api/model/notification.ts/~/NotificationRow.html","deprecated":false},{"id":"namespace_notificationrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"NotificationRow.id","file":"api/model/notification.ts","doc":"","url":"./api/model/notification.ts/~/NotificationRow.id.html","deprecated":false},{"id":"namespace_notificationrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"NotificationRow.user_id","file":"api/model/notification.ts","doc":"","url":"./api/model/notification.ts/~/NotificationRow.user_id.html","deprecated":false},{"id":"namespace_notificationrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"NotificationRow.type","file":"api/model/notification.ts","doc":"A NotificationType, not checked by the guard.","url":"./api/model/notification.ts/~/NotificationRow.type.html","deprecated":false},{"id":"namespace_notificationrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"NotificationRow.data","file":"api/model/notification.ts","doc":"The NotificationData as JSON, not checked by the guard.","url":"./api/model/notification.ts/~/NotificationRow.data.html","deprecated":false},{"id":"namespace_notificationrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"NotificationRow.read","file":"api/model/notification.ts","doc":"0 or 1.","url":"./api/model/notification.ts/~/NotificationRow.read.html","deprecated":false},{"id":"namespace_notificationrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"NotificationRow.created_at","file":"api/model/notification.ts","doc":"","url":"./api/model/notification.ts/~/NotificationRow.created_at.html","deprecated":false},{"id":"namespace_notificationrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"NotificationRow.source_key","file":"api/model/notification.ts","doc":"Names the event that caused the notification. A unique index keeps a second row with the same (user_id, source_key) out; null allows duplicates.","url":"./api/model/notification.ts/~/NotificationRow.source_key.html","deprecated":false},{"id":"namespace_isnotificationrow","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isNotificationRow","file":"api/model/notification.ts","doc":"Checks whether obj, a row getNotificationsForUser selected, is a NotificationRow.","url":"./api/model/notification.ts/~/isNotificationRow.html","deprecated":false},{"id":"namespace_notificationrowtoapi","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"notificationRowToApi","file":"api/model/notification.ts","doc":"Converts a row to the Notification the client gets.","url":"./api/model/notification.ts/~/notificationRowToApi.html","deprecated":false},{"id":"namespace_passwordresettokenrow","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PasswordResetTokenRow","file":"api/model/password-reset.ts","doc":"Stored by requestPasswordReset when it emails a reset link, and read back by resetPassword when the link is used.","url":"./api/model/password-reset.ts/~/PasswordResetTokenRow.html","deprecated":false},{"id":"namespace_passwordresettokenrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PasswordResetTokenRow.token","file":"api/model/password-reset.ts","doc":"The signed token itself, which the reset link carries.","url":"./api/model/password-reset.ts/~/PasswordResetTokenRow.token.html","deprecated":false},{"id":"namespace_passwordresettokenrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PasswordResetTokenRow.user_id","file":"api/model/password-reset.ts","doc":"","url":"./api/model/password-reset.ts/~/PasswordResetTokenRow.user_id.html","deprecated":false},{"id":"namespace_passwordresettokenrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PasswordResetTokenRow.expires_at","file":"api/model/password-reset.ts","doc":"Lets db/startup.ts purge old rows. The token's own exp is what ends the link.","url":"./api/model/password-reset.ts/~/PasswordResetTokenRow.expires_at.html","deprecated":false},{"id":"namespace_passwordresettokenrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PasswordResetTokenRow.used_at","file":"api/model/password-reset.ts","doc":"Set when the link is used, and reset to null if the reset then fails.","url":"./api/model/password-reset.ts/~/PasswordResetTokenRow.used_at.html","deprecated":false},{"id":"namespace_ispasswordresettokenrow","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isPasswordResetTokenRow","file":"api/model/password-reset.ts","doc":"Checks whether obj, a row resetPassword selected, is a PasswordResetTokenRow.","url":"./api/model/password-reset.ts/~/isPasswordResetTokenRow.html","deprecated":false},{"id":"namespace_playlistrow","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PlaylistRow","file":"api/model/playlist.ts","doc":"Returned by the playlist and follow services' SELECTs on playlists, which join the owner's name as owner_username. A query may add the dump_count and last_dump_at columns (VISIBLE_DUMP_FIGURES), which playlistRowToApi carries over when present.","url":"./api/model/playlist.ts/~/PlaylistRow.html","deprecated":false},{"id":"namespace_playlistrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistRow.id","file":"api/model/playlist.ts","doc":"","url":"./api/model/playlist.ts/~/PlaylistRow.id.html","deprecated":false},{"id":"namespace_playlistrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistRow.user_id","file":"api/model/playlist.ts","doc":"","url":"./api/model/playlist.ts/~/PlaylistRow.user_id.html","deprecated":false},{"id":"namespace_playlistrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistRow.title","file":"api/model/playlist.ts","doc":"","url":"./api/model/playlist.ts/~/PlaylistRow.title.html","deprecated":false},{"id":"namespace_playlistrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistRow.slug","file":"api/model/playlist.ts","doc":"Unique among its owner's playlists, and set on every row since 0021.","url":"./api/model/playlist.ts/~/PlaylistRow.slug.html","deprecated":false},{"id":"namespace_playlistrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistRow.owner_username","file":"api/model/playlist.ts","doc":"","url":"./api/model/playlist.ts/~/PlaylistRow.owner_username.html","deprecated":false},{"id":"namespace_playlistrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistRow.description","file":"api/model/playlist.ts","doc":"","url":"./api/model/playlist.ts/~/PlaylistRow.description.html","deprecated":false},{"id":"namespace_playlistrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistRow.is_public","file":"api/model/playlist.ts","doc":"","url":"./api/model/playlist.ts/~/PlaylistRow.is_public.html","deprecated":false},{"id":"namespace_playlistrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistRow.created_at","file":"api/model/playlist.ts","doc":"","url":"./api/model/playlist.ts/~/PlaylistRow.created_at.html","deprecated":false},{"id":"namespace_playlistrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistRow.updated_at","file":"api/model/playlist.ts","doc":"","url":"./api/model/playlist.ts/~/PlaylistRow.updated_at.html","deprecated":false},{"id":"namespace_playlistrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistRow.image_mime","file":"api/model/playlist.ts","doc":"","url":"./api/model/playlist.ts/~/PlaylistRow.image_mime.html","deprecated":false},{"id":"namespace_isplaylistrow","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isPlaylistRow","file":"api/model/playlist.ts","doc":"Checks whether a row node:sqlite returned is a PlaylistRow.","url":"./api/model/playlist.ts/~/isPlaylistRow.html","deprecated":false},{"id":"namespace_playlistrowtoapi","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"playlistRowToApi","file":"api/model/playlist.ts","doc":"Converts row to the Playlist the playlist routes send.","url":"./api/model/playlist.ts/~/playlistRowToApi.html","deprecated":false},{"id":"namespace_parserows","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"parseRows","file":"api/model/rows.ts","doc":"Returns rows turned by toApi, once isRow has accepted each.","url":"./api/model/rows.ts/~/parseRows.html","deprecated":false},{"id":"namespace_usersettingsrow","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UserSettingsRow","file":"api/model/settings.ts","doc":"Stored by updateSettings and read back by getSettings. A user without a row has the defaults.","url":"./api/model/settings.ts/~/UserSettingsRow.html","deprecated":false},{"id":"namespace_usersettingsrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserSettingsRow.user_id","file":"api/model/settings.ts","doc":"","url":"./api/model/settings.ts/~/UserSettingsRow.user_id.html","deprecated":false},{"id":"namespace_usersettingsrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserSettingsRow.style","file":"api/model/settings.ts","doc":"A style name, or null for the instance's.","url":"./api/model/settings.ts/~/UserSettingsRow.style.html","deprecated":false},{"id":"namespace_usersettingsrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserSettingsRow.color_scheme","file":"api/model/settings.ts","doc":"","url":"./api/model/settings.ts/~/UserSettingsRow.color_scheme.html","deprecated":false},{"id":"namespace_usersettingsrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserSettingsRow.digest_weekly","file":"api/model/settings.ts","doc":"0 or 1.","url":"./api/model/settings.ts/~/UserSettingsRow.digest_weekly.html","deprecated":false},{"id":"namespace_usersettingsrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserSettingsRow.digest_monthly","file":"api/model/settings.ts","doc":"0 or 1.","url":"./api/model/settings.ts/~/UserSettingsRow.digest_monthly.html","deprecated":false},{"id":"namespace_usersettingsrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserSettingsRow.updated_at","file":"api/model/settings.ts","doc":"","url":"./api/model/settings.ts/~/UserSettingsRow.updated_at.html","deprecated":false},{"id":"namespace_settings_columns","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"SETTINGS_COLUMNS","file":"api/model/settings.ts","doc":"Names the column of each setting, for the queries that pick users by one, as digest-service.ts does by its digest's switch.","url":"./api/model/settings.ts/~/SETTINGS_COLUMNS.html","deprecated":false},{"id":"namespace_isusersettingsrow","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isUserSettingsRow","file":"api/model/settings.ts","doc":"Checks whether obj, a row getSettings selected, is a UserSettingsRow.","url":"./api/model/settings.ts/~/isUserSettingsRow.html","deprecated":false},{"id":"namespace_settingsrowtoapi","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"settingsRowToApi","file":"api/model/settings.ts","doc":"Converts a row to the UserSettings the client gets. A style or scheme the code no longer knows, as after one is removed, reads as unset.","url":"./api/model/settings.ts/~/settingsRowToApi.html","deprecated":false},{"id":"namespace_user","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"User","file":"api/model/user.ts","doc":"Returned by the lookups of user-service.ts. It must never be sent as is: it carries the password hash.","url":"./api/model/user.ts/~/User.html","deprecated":false},{"id":"namespace_user","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"User.passwordHash","file":"api/model/user.ts","doc":"From hashPassword, as hash.salt, or null for an account from another instance (isRemoteUser), which signs in there and never with a password here. The row stores that as ''.","url":"./api/model/user.ts/~/User.passwordHash.html","deprecated":false},{"id":"namespace_isremoteuser","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isRemoteUser","file":"api/model/user.ts","doc":"Checks whether user's account lives on another instance, whose user signs in here through federation (federation-service.ts). Their password, email, avatar and name are that instance's to change, so the routes that change them here refuse.","url":"./api/model/user.ts/~/isRemoteUser.html","deprecated":false},{"id":"namespace_topublicuser","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"toPublicUser","file":"api/model/user.ts","doc":"Returns what anyone may see of user, without the hash and the email. Every route that sends another user's profile goes through it.","url":"./api/model/user.ts/~/toPublicUser.html","deprecated":false},{"id":"namespace_toselfuser","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"toSelfUser","file":"api/model/user.ts","doc":"Returns what user sees of themselves, without the hash, for the routes that answer the caller's own account.","url":"./api/model/user.ts/~/toSelfUser.html","deprecated":false},{"id":"namespace_userrow","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UserRow","file":"api/model/user.ts","doc":"Selected by user-service.ts and follow-service.ts, and converted by userRowToApi. It leaves out chat_read_at and tokens_valid_after, which only the chat's read state and getSessionState query.","url":"./api/model/user.ts/~/UserRow.html","deprecated":false},{"id":"namespace_userrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserRow.id","file":"api/model/user.ts","doc":"","url":"./api/model/user.ts/~/UserRow.id.html","deprecated":false},{"id":"namespace_userrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserRow.username","file":"api/model/user.ts","doc":"","url":"./api/model/user.ts/~/UserRow.username.html","deprecated":false},{"id":"namespace_userrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserRow.password_hash","file":"api/model/user.ts","doc":"'' for an account from another instance, which has no password.","url":"./api/model/user.ts/~/UserRow.password_hash.html","deprecated":false},{"id":"namespace_userrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserRow.role","file":"api/model/user.ts","doc":"","url":"./api/model/user.ts/~/UserRow.role.html","deprecated":false},{"id":"namespace_userrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserRow.created_at","file":"api/model/user.ts","doc":"","url":"./api/model/user.ts/~/UserRow.created_at.html","deprecated":false},{"id":"namespace_userrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserRow.updated_at","file":"api/model/user.ts","doc":"Bumped by any profile or avatar change.","url":"./api/model/user.ts/~/UserRow.updated_at.html","deprecated":false},{"id":"namespace_userrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserRow.avatar_mime","file":"api/model/user.ts","doc":"Null without an avatar.","url":"./api/model/user.ts/~/UserRow.avatar_mime.html","deprecated":false},{"id":"namespace_userrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserRow.description","file":"api/model/user.ts","doc":"Markdown.","url":"./api/model/user.ts/~/UserRow.description.html","deprecated":false},{"id":"namespace_userrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserRow.invited_by","file":"api/model/user.ts","doc":"Null for the seeded admin, who had no inviter.","url":"./api/model/user.ts/~/UserRow.invited_by.html","deprecated":false},{"id":"namespace_userrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserRow.invited_by_username","file":"api/model/user.ts","doc":"Joined from the inviter's row rather than stored, and undefined when the query doesn't join it. The guard doesn't check it.","url":"./api/model/user.ts/~/UserRow.invited_by_username.html","deprecated":false},{"id":"namespace_userrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserRow.email","file":"api/model/user.ts","doc":"","url":"./api/model/user.ts/~/UserRow.email.html","deprecated":false},{"id":"namespace_isuserrow","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isUserRow","file":"api/model/user.ts","doc":"Checks whether obj, a row selected with the columns of UserRow, is one.","url":"./api/model/user.ts/~/isUserRow.html","deprecated":false},{"id":"namespace_userrowtoapi","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"userRowToApi","file":"api/model/user.ts","doc":"Converts a row to a User, turning nulls into undefined.","url":"./api/model/user.ts/~/userRowToApi.html","deprecated":false},{"id":"namespace_userapitorow","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"userApiToRow","file":"api/model/user.ts","doc":"Converts a User back to a row, for updateUser. A User has no inviter id, so invited_by comes out null: don't write it back.","url":"./api/model/user.ts/~/userApiToRow.html","deprecated":false},{"id":"namespace_resolvebandcamp","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"resolveBandcamp","file":"api/remote/bandcamp-streams.ts","doc":"Returns the tracklist of the Bandcamp page pageUrl, from the cache when it was resolved in the last 12 hours. force skips the cache: the player sets it when it re-resolves a queue whose URLs expired or are about to, which a cached entry could hand back.","url":"./api/remote/bandcamp-streams.ts/~/resolveBandcamp.html","deprecated":false},{"id":"namespace_bandcamp_host_re","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"BANDCAMP_HOST_RE","file":"api/remote/bandcamp-tralbum.ts","doc":"Matches the hostnames bandcamp-streams.ts accepts: bandcamp.com and its subdomains, and not bandcamp.com.example.org. An artist on a custom domain doesn't match, and the player falls back to the embed.","url":"./api/remote/bandcamp-tralbum.ts/~/BANDCAMP_HOST_RE.html","deprecated":false},{"id":"namespace_parsetralbum","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"parseTralbum","file":"api/remote/bandcamp-tralbum.ts","doc":"Returns the release on the Bandcamp page html, fetched from sourceUrl; null when the page has no release data, no audio or no streamable track. Stream URLs outside bcbits.com are dropped.","url":"./api/remote/bandcamp-tralbum.ts/~/parseTralbum.html","deprecated":false},{"id":"namespace_max_page_bytes","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"MAX_PAGE_BYTES","file":"api/remote/fetch.ts","doc":"The default cap of readTextCapped. The metadata previews read is in the <head>, and a page past this is a download.","url":"./api/remote/fetch.ts/~/MAX_PAGE_BYTES.html","deprecated":false},{"id":"namespace_readbytescapped","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"readBytesCapped","file":"api/remote/fetch.ts","doc":"Reads the body of res up to maxBytes; the rest is cancelled, never downloaded. The image proxy reads through it, and readTextCapped.","url":"./api/remote/fetch.ts/~/readBytesCapped.html","deprecated":false},{"id":"namespace_readtextcapped","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"readTextCapped","file":"api/remote/fetch.ts","doc":"Reads the body of res as text, up to maxBytes, in the charset the page declares; the rest is cancelled, never downloaded. fetchPage and the Bandcamp and YouTube resolvers read pages through it.","url":"./api/remote/fetch.ts/~/readTextCapped.html","deprecated":false},{"id":"namespace_fetchwithtimeout","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"fetchWithTimeout","file":"api/remote/fetch.ts","doc":"Fetches a user-supplied URL, following up to five redirects, each of which must resolve to a public address too. timeoutMs bounds each hop, body included. The caller must read or cancel the body, or its connection stays open.","url":"./api/remote/fetch.ts/~/fetchWithTimeout.html","deprecated":false},{"id":"namespace_fetchedpage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"FetchedPage","file":"api/remote/fetch.ts","doc":"Returned by fetchPage to the link preview providers.","url":"./api/remote/fetch.ts/~/FetchedPage.html","deprecated":false},{"id":"namespace_fetchedpage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FetchedPage.url","file":"api/remote/fetch.ts","doc":"The URL the page was served from, after redirects: the base its relative links resolve against.","url":"./api/remote/fetch.ts/~/FetchedPage.url.html","deprecated":false},{"id":"namespace_fetchedpage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FetchedPage.html","file":"api/remote/fetch.ts","doc":"The page's text, up to MAX_PAGE_BYTES; missing when it isn't HTML.","url":"./api/remote/fetch.ts/~/FetchedPage.html.html","deprecated":false},{"id":"namespace_fetchpage","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"fetchPage","file":"api/remote/fetch.ts","doc":"Fetches a page for its link preview, through fetchWithTimeout. A response that isn't HTML is cancelled unread.","url":"./api/remote/fetch.ts/~/fetchPage.html","deprecated":false},{"id":"namespace_isvalidhttpurl","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isValidHttpUrl","file":"api/remote/fetch.ts","doc":"Checks whether raw is an http(s) URL on a host that isn't private, or a link to one of this site's own pages. Routes and services check a URL with it before storing, previewing or proxying it; it does no DNS lookup, which fetchWithTimeout does.","url":"./api/remote/fetch.ts/~/isValidHttpUrl.html","deprecated":false},{"id":"namespace_assertreachable","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"assertReachable","file":"api/remote/gerbeur-instance.ts","doc":"Checks that url may be reached: https on a public address, or anything under GERBEUR_FEDERATION_ALLOW_PRIVATE.","url":"./api/remote/gerbeur-instance.ts/~/assertReachable.html","deprecated":false},{"id":"namespace_fetchmetadata","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"fetchMetadata","file":"api/remote/gerbeur-instance.ts","doc":"Returns the metadata of the instance at origin, its issuer, cached. It must name origin as its issuer and speak this protocol's version.","url":"./api/remote/gerbeur-instance.ts/~/fetchMetadata.html","deprecated":false},{"id":"namespace_resolveissuer","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"resolveIssuer","file":"api/remote/gerbeur-instance.ts","doc":"Returns the issuer of the instance at origin, cached: origin itself, or, when origin is where the instance's pages are and its API lives at another, the issuer the pages' metadata names, whose own metadata must name those pages back as where its /authorize is. People know an instance by the address in their browser, which a sign-in form or the trust list may be given; a handle and the stored identities name the issuer.","url":"./api/remote/gerbeur-instance.ts/~/resolveIssuer.html","deprecated":false},{"id":"namespace_fetchkeys","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"fetchKeys","file":"api/remote/gerbeur-instance.ts","doc":"Returns the public keys of the instance at origin, cached unless fresh asks to refetch them and they weren't in the last minute.","url":"./api/remote/gerbeur-instance.ts/~/fetchKeys.html","deprecated":false},{"id":"namespace_exchangecode","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"exchangeCode","file":"api/remote/gerbeur-instance.ts","doc":"Trades code for an identity token at the token endpoint of the instance at origin, and returns the token, unverified.","url":"./api/remote/gerbeur-instance.ts/~/exchangeCode.html","deprecated":false},{"id":"namespace_postevent","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"postEvent","file":"api/remote/gerbeur-instance.ts","doc":"Sends the signed event event to the events endpoint of the instance at origin, and returns whether it took it. A 4xx other than 429 means it never will, which the caller treats as delivered.","url":"./api/remote/gerbeur-instance.ts/~/postEvent.html","deprecated":false},{"id":"namespace_fetchavatar","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"fetchAvatar","file":"api/remote/gerbeur-instance.ts","doc":"Returns the image at url, a user's avatar on their home instance, up to the size an avatar may be.","url":"./api/remote/gerbeur-instance.ts/~/fetchAvatar.html","deprecated":false},{"id":"namespace_clearinstancecaches","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"clearInstanceCaches","file":"api/remote/gerbeur-instance.ts","doc":"Empties the caches, for the tests' reset between cases.","url":"./api/remote/gerbeur-instance.ts/~/clearInstanceCaches.html","deprecated":false},{"id":"namespace_decodehtmlentities","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"decodeHtmlEntities","file":"api/remote/html.ts","doc":"Decodes the entities in str in a single pass, so &quot; reads ". An entity it doesn't know, or a code point that doesn't exist, is left as written. Also used by bandcamp-tralbum.ts on the JSON a page carries in an attribute.","url":"./api/remote/html.ts/~/decodeHtmlEntities.html","deprecated":false},{"id":"namespace_absolutehttpurl","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"absoluteHttpUrl","file":"api/remote/html.ts","doc":"Returns raw resolved against base as an absolute http(s) URL; undefined for a data: URI, another scheme or a URL that doesn't parse. Every URL a page names goes through it, so /og.png and //cdn/og.png work.","url":"./api/remote/html.ts/~/absoluteHttpUrl.html","deprecated":false},{"id":"namespace_jsonldresult","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"JsonLdResult","file":"api/remote/html.ts","doc":"Returned by the JSON-LD reading of parsePage, which the generic preview ranks below the page's OG and Twitter tags.","url":"./api/remote/html.ts/~/JsonLdResult.html","deprecated":false},{"id":"namespace_jsonldresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"JsonLdResult.title","file":"api/remote/html.ts","doc":"From name, or else headline.","url":"./api/remote/html.ts/~/JsonLdResult.title.html","deprecated":false},{"id":"namespace_jsonldresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"JsonLdResult.description","file":"api/remote/html.ts","doc":"","url":"./api/remote/html.ts/~/JsonLdResult.description.html","deprecated":false},{"id":"namespace_jsonldresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"JsonLdResult.thumbnailUrl","file":"api/remote/html.ts","doc":"From image, or else thumbnailUrl or thumbnail.","url":"./api/remote/html.ts/~/JsonLdResult.thumbnailUrl.html","deprecated":false},{"id":"namespace_page","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"Page","file":"api/remote/html.ts","doc":"Returned by parsePage: what a page says about itself, entities decoded, values trimmed and URLs absolute.","url":"./api/remote/html.ts/~/Page.html","deprecated":false},{"id":"namespace_page","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"Page.meta","file":"api/remote/html.ts","doc":"Returns the content of the first <meta> whose property or name is key, in any case: sites write og: tags under either attribute, and Twitter's too.","url":"./api/remote/html.ts/~/Page.meta.html","deprecated":false},{"id":"namespace_page","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Page.title","file":"api/remote/html.ts","doc":"The text of the <title> element.","url":"./api/remote/html.ts/~/Page.title.html","deprecated":false},{"id":"namespace_page","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Page.jsonLd","file":"api/remote/html.ts","doc":"","url":"./api/remote/html.ts/~/Page.jsonLd.html","deprecated":false},{"id":"namespace_page","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Page.themeColor","file":"api/remote/html.ts","doc":"The theme-color, as written: pass it to normalizeCssColor.","url":"./api/remote/html.ts/~/Page.themeColor.html","deprecated":false},{"id":"namespace_page","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Page.maskIconColor","file":"api/remote/html.ts","doc":"The color of the Safari pinned-tab icon, as written.","url":"./api/remote/html.ts/~/Page.maskIconColor.html","deprecated":false},{"id":"namespace_page","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Page.bestIcon","file":"api/remote/html.ts","doc":"The largest icon the page links, which the thumbnail placeholder draws.","url":"./api/remote/html.ts/~/Page.bestIcon.html","deprecated":false},{"id":"namespace_page","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Page.largeImage","file":"api/remote/html.ts","doc":"The first image declared at least 200 pixels both ways.","url":"./api/remote/html.ts/~/Page.largeImage.html","deprecated":false},{"id":"namespace_page","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Page.firstContentImage","file":"api/remote/html.ts","doc":"The first image that doesn't look like page furniture.","url":"./api/remote/html.ts/~/Page.firstContentImage.html","deprecated":false},{"id":"namespace_parsepage","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"parsePage","file":"api/remote/html.ts","doc":"Reads html, served from pageUrl, in one pass. The generic preview and the providers built on it read a page through it.","url":"./api/remote/html.ts/~/parsePage.html","deprecated":false},{"id":"namespace_normalizecsscolor","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"normalizeCssColor","file":"api/remote/html.ts","doc":"Returns raw as a lowercase #rrggbb, from a hex, rgb(), rgba() or common named color; undefined for any other form. The generic preview stores it as the preview's accentColor, a tint over the app's own surface, so alpha is dropped, and a fully transparent one is no color at all.","url":"./api/remote/html.ts/~/normalizeCssColor.html","deprecated":false},{"id":"namespace_proxiedimage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ProxiedImage","file":"api/remote/image-proxy.ts","doc":"Returned to GET /api/remote/image by fetchProxiedImage, which sends it back under contentType.","url":"./api/remote/image-proxy.ts/~/ProxiedImage.html","deprecated":false},{"id":"namespace_proxiedimage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ProxiedImage.bytes","file":"api/remote/image-proxy.ts","doc":"","url":"./api/remote/image-proxy.ts/~/ProxiedImage.bytes.html","deprecated":false},{"id":"namespace_proxiedimage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ProxiedImage.contentType","file":"api/remote/image-proxy.ts","doc":"One of the raster types, without parameters.","url":"./api/remote/image-proxy.ts/~/ProxiedImage.contentType.html","deprecated":false},{"id":"namespace_clearimagecache","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"clearImageCache","file":"api/remote/image-proxy.ts","doc":"Empties the cache, for the tests' reset between cases.","url":"./api/remote/image-proxy.ts/~/clearImageCache.html","deprecated":false},{"id":"namespace_fetchproxiedimage","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"fetchProxiedImage","file":"api/remote/image-proxy.ts","doc":"Returns the image at url, from the cache or else from its host; null when the host answers with an error, or with anything but a raster image of 5 MB at most. With width, it comes as a WebP copy scaled down to it, or as it is when no copy can be made (scalableImage, and ffmpeg). The route checks url with isValidHttpUrl first.","url":"./api/remote/image-proxy.ts/~/fetchProxiedImage.html","deprecated":false},{"id":"namespace_bandcampprovider","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"bandcampProvider","file":"api/remote/providers/bandcamp.ts","doc":"Claims bandcamp.com and its subdomains, where artists have their pages, and takes the embed player's URL from the page's og:video. The native player fetches the page's streams itself at play time, through GET /api/remote/bandcamp.","url":"./api/remote/providers/bandcamp.ts/~/bandcampProvider.html","deprecated":false},{"id":"namespace_genericpreview","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"genericPreview","file":"api/remote/providers/generic.ts","doc":"Returns the preview of the page url that page read, served from finalUrl after redirects. Each field falls back from OG tags to Twitter tags, JSON-LD and the markup itself. The icon and brand color feed the placeholder the frontend draws when there is no thumbnail.","url":"./api/remote/providers/generic.ts/~/genericPreview.html","deprecated":false},{"id":"namespace_genericprovider","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"genericProvider","file":"api/remote/providers/generic.ts","doc":"Matches every URL, so it comes last in the service's list.","url":"./api/remote/providers/generic.ts/~/genericProvider.html","deprecated":false},{"id":"namespace_richcontentprovider","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"RichContentProvider","file":"api/remote/providers/provider.ts","doc":"Implemented by each file of remote/providers/, and listed in priority order by rich-content-service.ts.","url":"./api/remote/providers/provider.ts/~/RichContentProvider.html","deprecated":false},{"id":"namespace_richcontentprovider","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"RichContentProvider.matches","file":"api/remote/providers/provider.ts","doc":"Called on a URL that isValidHttpUrl accepted; never throws.","url":"./api/remote/providers/provider.ts/~/RichContentProvider.matches.html","deprecated":false},{"id":"namespace_richcontentprovider","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"RichContentProvider.fetch","file":"api/remote/providers/provider.ts","doc":"Returns the preview of url, which ends up in the dump's rich_content or the create form's preview. It rejects when the page can't be fetched or answers with an error status, and the service then falls back to a stub. A page that isn't HTML yields a preview without metadata. The service tidies what it returns, so a provider leaves text as the page wrote it.","url":"./api/remote/providers/provider.ts/~/RichContentProvider.fetch.html","deprecated":false},{"id":"namespace_richcontentprovider","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RichContentProvider.name","file":"api/remote/providers/provider.ts","doc":"","url":"./api/remote/providers/provider.ts/~/RichContentProvider.name.html","deprecated":false},{"id":"namespace_selfprovider","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"selfProvider","file":"api/remote/providers/self.ts","doc":"Comes before the generic provider, and claims what isSelfUrl accepts. A profile's tab previews as the profile. Its fetch rejects with a 404 APIException for a missing page, a private dump or a private playlist: the preview is stored in the linking dump, which others may see.","url":"./api/remote/providers/self.ts/~/selfProvider.html","deprecated":false},{"id":"namespace_soundcloudprovider","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"soundcloudProvider","file":"api/remote/providers/soundcloud.ts","doc":"Claims SoundCloud's hosts, short links included, and builds the embed player's URL from the page's address.","url":"./api/remote/providers/soundcloud.ts/~/soundcloudProvider.html","deprecated":false},{"id":"namespace_youtubeprovider","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"youtubeProvider","file":"api/remote/providers/youtube.ts","doc":"Comes first in the service's list. A video's embed keeps the link's playlist and start time, a playlist embeds as a videoseries, and a channel gets no embed. Its fetch never rejects: whatever YouTube doesn't answer is left out.","url":"./api/remote/providers/youtube.ts/~/youtubeProvider.html","deprecated":false},{"id":"namespace_isprivateaddress","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isPrivateAddress","file":"api/remote/public-address.ts","doc":"Checks whether ip is an IPv4 or IPv6 address outside the public internet. An IPv4 address carried in IPv6 is judged as IPv4. Anything that isn't an IP address is false, so a hostname must be resolved first.","url":"./api/remote/public-address.ts/~/isPrivateAddress.html","deprecated":false},{"id":"namespace_barehostname","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"bareHostname","file":"api/remote/public-address.ts","doc":"Returns url's hostname without the brackets URL.hostname keeps around an IPv6 literal: the address checks here read it, and fetch.ts hands it to curl's --resolve.","url":"./api/remote/public-address.ts/~/bareHostname.html","deprecated":false},{"id":"namespace_isprivatehostname","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isPrivateHostname","file":"api/remote/public-address.ts","doc":"Checks whether the host of url is private without a DNS lookup: a private IP address, or localhost and its subdomains. isValidHttpUrl uses it to reject a link early; only resolvePublicAddress is a real guard.","url":"./api/remote/public-address.ts/~/isPrivateHostname.html","deprecated":false},{"id":"namespace_resolvepublicaddress","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"resolvePublicAddress","file":"api/remote/public-address.ts","doc":"Resolves the host of url and returns one of its addresses, all of which must be public: the fetch may pick any of them. fetchWithTimeout calls it before each hop.Only the curl fallback connects to the address returned. Deno's fetch resolves the name again, so a DNS server that answers differently the second time (rebinding) can still get through.","url":"./api/remote/public-address.ts/~/resolvePublicAddress.html","deprecated":false},{"id":"namespace_fetchtwemojisvg","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"fetchTwemojiSvg","file":"api/remote/twemoji.ts","doc":"Returns Twemoji's SVG for emoji, whose file name cp comes from emojiToCodepoint. emoji only serves the error message. It fetches with plain fetch, since the host is fixed, and gives up after 15 s.","url":"./api/remote/twemoji.ts/~/fetchTwemojiSvg.html","deprecated":false},{"id":"namespace_parseplaylistpage","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"parsePlaylistPage","file":"api/remote/youtube-playlist.ts","doc":"Returns the playlist listId as read from its page html; null when the page has no ytInitialData or no track in it.","url":"./api/remote/youtube-playlist.ts/~/parsePlaylistPage.html","deprecated":false},{"id":"namespace_resolveyoutubeplaylist","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"resolveYouTubePlaylist","file":"api/remote/youtube-playlist.ts","doc":"Returns the tracklist of the playlist listId, from the cache when it was resolved in the last 6 hours.","url":"./api/remote/youtube-playlist.ts/~/resolveYouTubePlaylist.html","deprecated":false},{"id":"namespace_default","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"default","file":"api/routes/attachments.ts","doc":"Mounted by api/main.ts behind the error, Open Graph and CORS middleware. An APIException thrown by a handler becomes the JSON error response there.","url":"./api/routes/attachments.ts/~/default.html","deprecated":false},{"id":"namespace_default","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"default","file":"api/routes/avatars.ts","doc":"Mounted by api/main.ts behind the error, Open Graph and CORS middleware. An APIException thrown by a handler becomes the JSON error response there.","url":"./api/routes/avatars.ts/~/default.html","deprecated":false},{"id":"namespace_default","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"default","file":"api/routes/categories.ts","doc":"Mounted by api/main.ts behind the error, Open Graph and CORS middleware. An APIException thrown by a handler becomes the JSON error response there.","url":"./api/routes/categories.ts/~/default.html","deprecated":false},{"id":"namespace_default","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"default","file":"api/routes/chat.ts","doc":"Mounted by api/main.ts behind the error, Open Graph and CORS middleware. An APIException thrown by a handler becomes the JSON error response there.","url":"./api/routes/chat.ts/~/default.html","deprecated":false},{"id":"namespace_default","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"default","file":"api/routes/comments.ts","doc":"Mounted by api/main.ts behind the error, Open Graph and CORS middleware. An APIException thrown by a handler becomes the JSON error response there.","url":"./api/routes/comments.ts/~/default.html","deprecated":false},{"id":"namespace_default","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"default","file":"api/routes/community.ts","doc":"Mounted by api/main.ts behind the error, Open Graph and CORS middleware. An APIException thrown by a handler becomes the JSON error response there.","url":"./api/routes/community.ts/~/default.html","deprecated":false},{"id":"namespace_default","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"default","file":"api/routes/dumps.ts","doc":"Mounted by api/main.ts behind the error, Open Graph and CORS middleware. An APIException thrown by a handler becomes the JSON error response there.","url":"./api/routes/dumps.ts/~/default.html","deprecated":false},{"id":"namespace_default","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"default","file":"api/routes/federation.ts","doc":"Mounted by api/main.ts behind the error, Open Graph and CORS middleware. An APIException thrown by a handler becomes the JSON error response there.","url":"./api/routes/federation.ts/~/default.html","deprecated":false},{"id":"namespace_default","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"default","file":"api/routes/files.ts","doc":"Mounted by api/main.ts behind the error, Open Graph and CORS middleware. An APIException thrown by a handler becomes the JSON error response there.","url":"./api/routes/files.ts/~/default.html","deprecated":false},{"id":"namespace_default","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"default","file":"api/routes/follows.ts","doc":"Mounted by api/main.ts behind the error, Open Graph and CORS middleware. An APIException thrown by a handler becomes the JSON error response there.","url":"./api/routes/follows.ts/~/default.html","deprecated":false},{"id":"namespace_default","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"default","file":"api/routes/invites.ts","doc":"Mounted by api/main.ts behind the error, Open Graph and CORS middleware. An APIException thrown by a handler becomes the JSON error response there.","url":"./api/routes/invites.ts/~/default.html","deprecated":false},{"id":"namespace_default","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"default","file":"api/routes/me.ts","doc":"Mounted by api/main.ts behind the error, Open Graph and CORS middleware. An APIException thrown by a handler becomes the JSON error response there.","url":"./api/routes/me.ts/~/default.html","deprecated":false},{"id":"namespace_default","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"default","file":"api/routes/notifications.ts","doc":"Mounted by api/main.ts behind the error, Open Graph and CORS middleware. An APIException thrown by a handler becomes the JSON error response there.","url":"./api/routes/notifications.ts/~/default.html","deprecated":false},{"id":"namespace_default","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"default","file":"api/routes/oauth.ts","doc":"Mounted by api/main.ts behind the error, Open Graph and CORS middleware. An APIException thrown by a handler becomes the JSON error response there.","url":"./api/routes/oauth.ts/~/default.html","deprecated":false},{"id":"namespace_default","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"default","file":"api/routes/password-resets.ts","doc":"Mounted by api/main.ts behind the error, Open Graph and CORS middleware. An APIException thrown by a handler becomes the JSON error response there.","url":"./api/routes/password-resets.ts/~/default.html","deprecated":false},{"id":"namespace_default","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"default","file":"api/routes/playlists.ts","doc":"Mounted by api/main.ts behind the error, Open Graph and CORS middleware. An APIException thrown by a handler becomes the JSON error response there.","url":"./api/routes/playlists.ts/~/default.html","deprecated":false},{"id":"namespace_default","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"default","file":"api/routes/remote.ts","doc":"Mounted by api/main.ts behind the error, Open Graph and CORS middleware. An APIException thrown by a handler becomes the JSON error response there.","url":"./api/routes/remote.ts/~/default.html","deprecated":false},{"id":"namespace_default","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"default","file":"api/routes/search.ts","doc":"Mounted by api/main.ts behind the error, Open Graph and CORS middleware. An APIException thrown by a handler becomes the JSON error response there.","url":"./api/routes/search.ts/~/default.html","deprecated":false},{"id":"namespace_default","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"default","file":"api/routes/sessions.ts","doc":"Mounted by api/main.ts behind the error, Open Graph and CORS middleware. An APIException thrown by a handler becomes the JSON error response there.","url":"./api/routes/sessions.ts/~/default.html","deprecated":false},{"id":"namespace_default","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"default","file":"api/routes/thumbnails.ts","doc":"Mounted by api/main.ts behind the error, Open Graph and CORS middleware. An APIException thrown by a handler becomes the JSON error response there.","url":"./api/routes/thumbnails.ts/~/default.html","deprecated":false},{"id":"namespace_default","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"default","file":"api/routes/unsubscribe.ts","doc":"Mounted by api/main.ts behind the error, Open Graph and CORS middleware. An APIException thrown by a handler becomes the JSON error response there.","url":"./api/routes/unsubscribe.ts/~/default.html","deprecated":false},{"id":"namespace_default","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"default","file":"api/routes/users.ts","doc":"Mounted by api/main.ts behind the error, Open Graph and CORS middleware. An APIException thrown by a handler becomes the JSON error response there.","url":"./api/routes/users.ts/~/default.html","deprecated":false},{"id":"namespace_default","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"default","file":"api/routes/waveforms.ts","doc":"Mounted by api/main.ts behind the error, Open Graph and CORS middleware. An APIException thrown by a handler becomes the JSON error response there.","url":"./api/routes/waveforms.ts/~/default.html","deprecated":false},{"id":"namespace_default","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"default","file":"api/routes/well-known.ts","doc":"Mounted by api/main.ts behind the error, Open Graph and CORS middleware. An APIException thrown by a handler becomes the JSON error response there.","url":"./api/routes/well-known.ts/~/default.html","deprecated":false},{"id":"namespace_default","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"default","file":"api/routes/ws.ts","doc":"Mounted by api/main.ts behind the error, Open Graph and CORS middleware. An APIException thrown by a handler becomes the JSON error response there.","url":"./api/routes/ws.ts/~/default.html","deprecated":false},{"id":"namespace_createattachment","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"createAttachment","file":"api/services/attachment-service.ts","doc":"Records attachment id once POST /api/attachments has written its file. Until a saved body links it, the startup purge deletes it after ORPHANED_ATTACHMENTS_RETENTION_HOURS.","url":"./api/services/attachment-service.ts/~/createAttachment.html","deprecated":false},{"id":"namespace_attachmentresourcetype","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"AttachmentResourceType","file":"api/services/attachment-service.ts","doc":"Stored in attachments.resource_type by bindAttachments, it names the kind of resource whose saved text links the attachment.","url":"./api/services/attachment-service.ts/~/AttachmentResourceType.html","deprecated":false},{"id":"namespace_attachmentaccess","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"AttachmentAccess","file":"api/services/attachment-service.ts","doc":"Returned to GET /api/attachments/:attachmentId by getAttachmentAccess. ownerId is set when only that user may see the image, because the resource linking it is private.","url":"./api/services/attachment-service.ts/~/AttachmentAccess.html","deprecated":false},{"id":"namespace_attachmentaccess","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AttachmentAccess.mime","file":"api/services/attachment-service.ts","doc":"","url":"./api/services/attachment-service.ts/~/AttachmentAccess.mime.html","deprecated":false},{"id":"namespace_attachmentaccess","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AttachmentAccess.ownerId","file":"api/services/attachment-service.ts","doc":"","url":"./api/services/attachment-service.ts/~/AttachmentAccess.ownerId.html","deprecated":false},{"id":"namespace_getattachmentaccess","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getAttachmentAccess","file":"api/services/attachment-service.ts","doc":"Returns attachment attachmentId's type and who may see it. An attachment nothing links yet is public, so the editor can show it before the text is saved; its id is unguessable. One linked by a private dump or playlist, or by a comment on a private dump, is its owner's.","url":"./api/services/attachment-service.ts/~/getAttachmentAccess.html","deprecated":false},{"id":"namespace_linkattachments","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"linkAttachments","file":"api/services/attachment-service.ts","doc":"Binds the attachments whose URLs appear in text to the resource that saved it, so the startup purge keeps them as long as that resource exists, and they are seen by whoever may see it. It is called whenever a dump, comment, chat message, playlist or profile description is saved. An attachment already bound stays with its resource, so pasting another's URL claims nothing, and removing the link from a body never unbinds it.","url":"./api/services/attachment-service.ts/~/linkAttachments.html","deprecated":false},{"id":"namespace_announcelinksnowpublic","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"announceLinksNowPublic","file":"api/services/backlink-service.ts","doc":"Tells clients that dump dumpId, which just turned public, is now related to the dumps linked to or from it, for the dump service. Its poster saw those links already; to everyone else they are new.","url":"./api/services/backlink-service.ts/~/announceLinksNowPublic.html","deprecated":false},{"id":"namespace_relinkbacklinks","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"relinkBacklinks","file":"api/services/backlink-service.ts","doc":"Replaces the backlinks from one text, a dump's note (dump_comment) or one of its comments (comment), with the links its current text holds. A link counts when it is a dump's page on this site (/@owner/dumps/<slug>), or when it is the URL a dump was posted with, compared by canonicalizeUrl as reposts are. The dump and comment services call it on every save, and with an empty text when a comment is deleted. Clients are told of the dumps it links or no longer links, as dump_related_changed.","url":"./api/services/backlink-service.ts/~/relinkBacklinks.html","deprecated":false},{"id":"namespace_getrelateddumps","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getRelatedDumps","file":"api/services/backlink-service.ts","doc":"Returns the dumps linked to or from dumpId, newest first and at most 20, without the private ones the requesting user can't see. It doesn't check dumpId itself: GET /api/dumps/:dumpId/related does that first.","url":"./api/services/backlink-service.ts/~/getRelatedDumps.html","deprecated":false},{"id":"namespace_getcategorybyid","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getCategoryById","file":"api/services/category-service.ts","doc":"Returns category id, for updateCategory.","url":"./api/services/category-service.ts/~/getCategoryById.html","deprecated":false},{"id":"namespace_getcategorybyslug","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getCategoryBySlug","file":"api/services/category-service.ts","doc":"Returns the category of kind at slug, for listDumpsByCategory and the list of every public playlist.","url":"./api/services/category-service.ts/~/getCategoryBySlug.html","deprecated":false},{"id":"namespace_getcategoryidbyslug","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getCategoryIdBySlug","file":"api/services/category-service.ts","doc":"Returns the id of the category of kind at slug, or undefined when there is none.","url":"./api/services/category-service.ts/~/getCategoryIdBySlug.html","deprecated":false},{"id":"namespace_resolvecategoryfilter","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"resolveCategoryFilter","file":"api/services/category-service.ts","doc":"Returns the id of the category of kind whose slug the name parameter of params, ?category= by default, gives, undefined without one, or \"missing\" when it names none, so that the list comes back empty rather than unfiltered. The users routes filter a profile's lists with it, and the search route its results.","url":"./api/services/category-service.ts/~/resolveCategoryFilter.html","deprecated":false},{"id":"namespace_categoryjoin","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"categoryJoin","file":"api/services/category-service.ts","doc":"Returns the join that keeps only the rows of alias, a dump or playlist as kind says, filed under categoryId, with its parameters, or nothing without one. A query puts the join after its FROM and the parameters before its own.","url":"./api/services/category-service.ts/~/categoryJoin.html","deprecated":false},{"id":"namespace_listcategories","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"listCategories","file":"api/services/category-service.ts","doc":"Returns every category, of both kinds, by kind, position then slug, for GET /api/categories.","url":"./api/services/category-service.ts/~/listCategories.html","deprecated":false},{"id":"namespace_createcategory","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"createCategory","file":"api/services/category-service.ts","doc":"Creates a category, for POST /api/categories. The name is stored trimmed, and the position defaults to 0. Every client is told to fetch the categories again, as after the two writes below.","url":"./api/services/category-service.ts/~/createCategory.html","deprecated":false},{"id":"namespace_updatecategory","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"updateCategory","file":"api/services/category-service.ts","doc":"Applies req to category id, for PUT /api/categories/:id, and returns the category as it now is. Fields req leaves out keep their value.","url":"./api/services/category-service.ts/~/updateCategory.html","deprecated":false},{"id":"namespace_deletecategory","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"deleteCategory","file":"api/services/category-service.ts","doc":"Deletes category id, for DELETE /api/categories/:id. Its dumps or playlists stay, and lose it from their categoryIds.","url":"./api/services/category-service.ts/~/deleteCategory.html","deprecated":false},{"id":"namespace_assertcategoriesexist","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"assertCategoriesExist","file":"api/services/category-service.ts","doc":"Checks that every id in categoryIds names a category of kind, so that a dump is never filed under a playlist category, nor the other way round. The dump and playlist services run it before they write a row or store an uploaded file, so a bad id fails the request before anything is written.","url":"./api/services/category-service.ts/~/assertCategoriesExist.html","deprecated":false},{"id":"namespace_setcategories","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"setCategories","file":"api/services/category-service.ts","doc":"Replaces the categories of the dump or playlist id, as kind says, with categoryIds, duplicates dropped. An empty list takes it out of every category. Called inside the dump or playlist service's transaction, it joins that one.","url":"./api/services/category-service.ts/~/setCategories.html","deprecated":false},{"id":"namespace_attachcategoryids","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"attachCategoryIds","file":"api/services/category-service.ts","doc":"Sets categoryIds on each of items, dumps or playlists as kind says, in place, in one query. Their rows don't carry them, so every service that returns dumps or playlists calls this first.","url":"./api/services/category-service.ts/~/attachCategoryIds.html","deprecated":false},{"id":"namespace_listdumpsbycategory","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"listDumpsByCategory","file":"api/services/category-service.ts","doc":"Returns a page of the dumps in the dump category at slug, newest first, for GET /api/dumps?category=. Private dumps are left out, except requestingUserId's own.","url":"./api/services/category-service.ts/~/listDumpsByCategory.html","deprecated":false},{"id":"namespace_createchatmessage","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"createChatMessage","file":"api/services/chat-service.ts","doc":"Stores a message from userId on a chat_send, and claims the pasted images it links to. A replyToId naming no message is dropped, and the message is posted as no reply. The message mentionsEveryone when it says @everyone and userId may. The caller broadcasts the result, and notifies everyone when it is flagged.","url":"./api/services/chat-service.ts/~/createChatMessage.html","deprecated":false},{"id":"namespace_chatmessagementionseveryone","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"chatMessageMentionsEveryone","file":"api/services/chat-service.ts","doc":"Checks whether message id is flagged mentionsEveryone, false when there is no such message. The WebSocket route reads it before an edit, to notify everyone only when the edit adds @everyone.","url":"./api/services/chat-service.ts/~/chatMessageMentionsEveryone.html","deprecated":false},{"id":"namespace_updatechatmessage","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"updateChatMessage","file":"api/services/chat-service.ts","doc":"Replaces a message's body on a chat_edit, and claims any image the new body links to. canModerate lets a moderator edit anyone's message. The flag mentionsEveryone is set again from the new body and the author's role, not the editor's: a moderator's edit can't make a user's message reach everyone. The caller broadcasts the result.","url":"./api/services/chat-service.ts/~/updateChatMessage.html","deprecated":false},{"id":"namespace_deletechatmessage","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"deleteChatMessage","file":"api/services/chat-service.ts","doc":"Deletes a message on a chat_delete. canModerate lets a moderator delete anyone's message. Replies to it keep their replyToId, without its preview.","url":"./api/services/chat-service.ts/~/deleteChatMessage.html","deprecated":false},{"id":"namespace_chatcursor","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ChatCursor","file":"api/services/chat-service.ts","doc":"Passed by routes/chat.ts to page through the history, from the message the client already has at one end. Messages are ordered by createdAt, then by id, so a page boundary between two messages sent in the same millisecond skips neither.","url":"./api/services/chat-service.ts/~/ChatCursor.html","deprecated":false},{"id":"namespace_chatcursor","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatCursor.createdAt","file":"api/services/chat-service.ts","doc":"An ISO timestamp, compared as a string with created_at.","url":"./api/services/chat-service.ts/~/ChatCursor.createdAt.html","deprecated":false},{"id":"namespace_chatcursor","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatCursor.id","file":"api/services/chat-service.ts","doc":"Without it, the cursor takes in every message at createdAt: they are all older for getRecentChatMessages and all newer for getChatMessagesAfter.","url":"./api/services/chat-service.ts/~/ChatCursor.id.html","deprecated":false},{"id":"namespace_getrecentchatmessages","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getRecentChatMessages","file":"api/services/chat-service.ts","doc":"Returns the latest limit messages, or with before the limit messages just older than it, oldest first either way. limit is clamped to 1–100.","url":"./api/services/chat-service.ts/~/getRecentChatMessages.html","deprecated":false},{"id":"namespace_getchatmessagesafter","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getChatMessagesAfter","file":"api/services/chat-service.ts","doc":"Returns the first limit messages after after, oldest first. The chatbox uses it to fetch what it missed while the socket was down. limit is clamped to 1–100.","url":"./api/services/chat-service.ts/~/getChatMessagesAfter.html","deprecated":false},{"id":"namespace_chatreadstate","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ChatReadState","file":"api/services/chat-service.ts","doc":"Returned to the WebSocket route by getChatReadState and markChatRead. The route sends it in welcome and in chat_read_update, and the client shows unread on the chat's badge.","url":"./api/services/chat-service.ts/~/ChatReadState.html","deprecated":false},{"id":"namespace_chatreadstate","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatReadState.readAt","file":"api/services/chat-service.ts","doc":"The created_at of the newest message the user has read.","url":"./api/services/chat-service.ts/~/ChatReadState.readAt.html","deprecated":false},{"id":"namespace_chatreadstate","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatReadState.unread","file":"api/services/chat-service.ts","doc":"Counts only the messages of other users after readAt.","url":"./api/services/chat-service.ts/~/ChatReadState.unread.html","deprecated":false},{"id":"namespace_getchatreadstate","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getChatReadState","file":"api/services/chat-service.ts","doc":"Returns how far userId has read the chat. A user who never opened it has read up to their registration, so the history from before it isn't unread.","url":"./api/services/chat-service.ts/~/getChatReadState.html","deprecated":false},{"id":"namespace_markchatread","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"markChatRead","file":"api/services/chat-service.ts","doc":"Moves userId's read marker to at, a message's created_at, on a chat_read. It never moves back, so a lagging tab can't undo a newer tab's read. It never passes the newest message, so a timestamp from the future can't mark messages read before they are sent.","url":"./api/services/chat-service.ts/~/markChatRead.html","deprecated":false},{"id":"namespace_likeresult","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"LikeResult","file":"api/services/comment-like-service.ts","doc":"Returned to the WebSocket route by castCommentLike and removeCommentLike. The route acks the liker with likeCount, then broadcasts it to every client, or to the liker's alone when the comment's dump isPrivate.","url":"./api/services/comment-like-service.ts/~/LikeResult.html","deprecated":false},{"id":"namespace_likeresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"LikeResult.likeCount","file":"api/services/comment-like-service.ts","doc":"","url":"./api/services/comment-like-service.ts/~/LikeResult.likeCount.html","deprecated":false},{"id":"namespace_likeresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"LikeResult.isPrivate","file":"api/services/comment-like-service.ts","doc":"","url":"./api/services/comment-like-service.ts/~/LikeResult.isPrivate.html","deprecated":false},{"id":"namespace_castcommentlike","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"castCommentLike","file":"api/services/comment-like-service.ts","doc":"Records userId's like on a comment and notifies the comment's author. The notification is best-effort: if it fails, the like still counts.","url":"./api/services/comment-like-service.ts/~/castCommentLike.html","deprecated":false},{"id":"namespace_removecommentlike","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"removeCommentLike","file":"api/services/comment-like-service.ts","doc":"Takes back userId's like on a comment. It doesn't check that the user can still see the comment, since a like on a dump that has gone private is still theirs to take back.","url":"./api/services/comment-like-service.ts/~/removeCommentLike.html","deprecated":false},{"id":"namespace_getusercommentlikes","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getUserCommentLikes","file":"api/services/comment-like-service.ts","doc":"Returns the ids of the comments userId likes. The WebSocket route sends them in its welcome message, and the client shows those like buttons pressed.","url":"./api/services/comment-like-service.ts/~/getUserCommentLikes.html","deprecated":false},{"id":"namespace_getcommentlikers","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getCommentLikers","file":"api/services/comment-like-service.ts","doc":"Returns a page of the users who like a comment, latest like first, for GET /api/comments/:commentId/likers. It doesn't check that the caller may see the comment: the route does that first, with getDump.","url":"./api/services/comment-like-service.ts/~/getCommentLikers.html","deprecated":false},{"id":"namespace_getcommentdumpid","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getCommentDumpId","file":"api/services/comment-service.ts","doc":"Returns the id of the dump comment commentId is posted under. The likers route uses it to check that the caller may see that dump.","url":"./api/services/comment-service.ts/~/getCommentDumpId.html","deprecated":false},{"id":"namespace_getcomments","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getComments","file":"api/services/comment-service.ts","doc":"Returns every comment on dump dumpId, oldest first, for GET /api/dumps/:dumpId/comments. Deleted comments are included, emptied, so the client can keep their replies in place.","url":"./api/services/comment-service.ts/~/getComments.html","deprecated":false},{"id":"namespace_createcomment","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"createComment","file":"api/services/comment-service.ts","doc":"Posts a comment on dump dumpId, replying to parentId if given, for POST /api/dumps/:dumpId/comments. It notifies the dump's poster and the users it mentions, unless the dump is private, and links the comment's attachments and backlinks. The route has checked that the caller may see the dump.","url":"./api/services/comment-service.ts/~/createComment.html","deprecated":false},{"id":"namespace_commentdump","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CommentDump","file":"api/services/comment-service.ts","doc":"The dump a comment is on, as updateComment and deleteComment return it: what the route needs to choose the broadcast's audience.","url":"./api/services/comment-service.ts/~/CommentDump.html","deprecated":false},{"id":"namespace_commentdump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentDump.id","file":"api/services/comment-service.ts","doc":"","url":"./api/services/comment-service.ts/~/CommentDump.id.html","deprecated":false},{"id":"namespace_commentdump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentDump.isPrivate","file":"api/services/comment-service.ts","doc":"","url":"./api/services/comment-service.ts/~/CommentDump.isPrivate.html","deprecated":false},{"id":"namespace_commentdump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentDump.userId","file":"api/services/comment-service.ts","doc":"The dump's poster, the only one who sees a private dump's comments.","url":"./api/services/comment-service.ts/~/CommentDump.userId.html","deprecated":false},{"id":"namespace_updatecomment","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"updateComment","file":"api/services/comment-service.ts","doc":"Replaces a comment's body, for PATCH /api/comments/:commentId. canModerate lets someone other than the author do it. It notifies, in the author's name, the users it mentions for the first time, unless the dump is private, and relinks the attachments and backlinks. The route broadcasts the comment to those who may see its dump.","url":"./api/services/comment-service.ts/~/updateComment.html","deprecated":false},{"id":"namespace_deletecomment","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"deleteComment","file":"api/services/comment-service.ts","doc":"Deletes a comment, for DELETE /api/comments/:commentId. canModerate lets someone other than the author do it. The body is emptied and the backlinks dropped, but the row stays so its replies keep their place. The route broadcasts the deletion to those who may see the returned dump.","url":"./api/services/comment-service.ts/~/deleteComment.html","deprecated":false},{"id":"namespace_communitystatsof","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"communityStatsOf","file":"api/services/community-service.ts","doc":"Returns what the site did from from to to: its most upvoted public dumps, who joined, the new public playlists, the chat's messages and the totals.","url":"./api/services/community-service.ts/~/communityStatsOf.html","deprecated":false},{"id":"namespace_refreshcommunitystats","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"refreshCommunityStats","file":"api/services/community-service.ts","doc":"Recomputes the figures of each period, ending at now.","url":"./api/services/community-service.ts/~/refreshCommunityStats.html","deprecated":false},{"id":"namespace_getcommunitystats","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getCommunityStats","file":"api/services/community-service.ts","doc":"Returns the figures of period as of the last refresh, for GET /api/community, refreshing them first if there are none yet.","url":"./api/services/community-service.ts/~/getCommunityStats.html","deprecated":false},{"id":"namespace_communityjob","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"communityJob","file":"api/services/community-service.ts","doc":"Refreshes the figures at startup, then every COMMUNITY_REFRESH_MINUTES. main.ts starts it.","url":"./api/services/community-service.ts/~/communityJob.html","deprecated":false},{"id":"namespace_listcommunityevents","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"listCommunityEvents","file":"api/services/community-service.ts","doc":"Returns the latest things done in public, newest first, FEED_MAX at most: the public dumps posted and playlists created, the comments and upvotes on public dumps, and who joined. A dump has one comment event and one upvote event at most, its latest, so that a thread or a popular dump doesn't fill the feed.Each part reads its FEED_MAX latest, which is all the whole may keep of it. The comments and the upvotes are grouped by dump first, and with MAX() SQLite fills a group's other columns from the row that holds the maximum: the latest comment's author and id, the latest voter.","url":"./api/services/community-service.ts/~/listCommunityEvents.html","deprecated":false},{"id":"namespace_getcommunityfeed","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getCommunityFeed","file":"api/services/community-service.ts","doc":"Returns the community feed for GET /api/community/feed: the latest events, read now, and the last week's figures as of the last refresh.","url":"./api/services/community-service.ts/~/getCommunityFeed.html","deprecated":false},{"id":"namespace_builddigest","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"buildDigest","file":"api/services/digest-service.ts","doc":"Returns the digest of user readerId for the period from from to to, or null when it would show nothing. The links are absolute; the unsubscribe one carries token, which turns off cadence.","url":"./api/services/digest-service.ts/~/buildDigest.html","deprecated":false},{"id":"namespace_syncdigestschedules","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"syncDigestSchedules","file":"api/services/digest-service.ts","doc":"Brings digest_schedule in line with the settings: a user who turned a cadence off loses its row, and one who receives it without a row, being new or having turned it back on, starts a period at now.","url":"./api/services/digest-service.ts/~/syncDigestSchedules.html","deprecated":false},{"id":"namespace_sendduedigests","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"sendDueDigests","file":"api/services/digest-service.ts","doc":"Sends every digest due at now, one after the other, and returns how many went out. A digest that fails to send is logged and not retried: its period is over either way, and the next one starts.","url":"./api/services/digest-service.ts/~/sendDueDigests.html","deprecated":false},{"id":"namespace_digestjob","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"digestJob","file":"api/services/digest-service.ts","doc":"Sends the due digests a minute after the server starts, then every quarter of an hour. main.ts starts it.","url":"./api/services/digest-service.ts/~/digestJob.html","deprecated":false},{"id":"namespace_createurldump","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"createUrlDump","file":"api/services/dump-service.ts","doc":"Posts a link as userId, for POST /api/dumps, with its preview fetched from the page. A public dump is broadcast as dump_created and notified to the poster's followers. Anyone @mentioned in the note is notified even when the dump is private.","url":"./api/services/dump-service.ts/~/createUrlDump.html","deprecated":false},{"id":"namespace_createfiledump","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"createFileDump","file":"api/services/dump-service.ts","doc":"Posts an uploaded file as userId, for POST /api/dumps, and stores it in DUMPS_DIR under the dump's id. It is announced and notified as createUrlDump does.","url":"./api/services/dump-service.ts/~/createFileDump.html","deprecated":false},{"id":"namespace_getdump","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getDump","file":"api/services/dump-service.ts","doc":"Returns dump dumpId as requestingUserId may see it. The routes resolve every :dumpId with it before acting on the dump.","url":"./api/services/dump-service.ts/~/getDump.html","deprecated":false},{"id":"namespace_getdumpbypath","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getDumpByPath","file":"api/services/dump-service.ts","doc":"Returns the dump of userId's whose slug is or was slug, as requestingUserId may see it, for GET /api/users/:key/dumps/:slug, which reads a dump by its page's path. Reached by a former slug, it comes with its current one, which the client puts in its URL.","url":"./api/services/dump-service.ts/~/getDumpByPath.html","deprecated":false},{"id":"namespace_searchdumps","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"searchDumps","file":"api/services/dump-service.ts","doc":"Returns a page of the dumps requestingUserId may see whose title, note, or previewed title or description contains query, newest first, with how many match in all, optionally only those in the dump category categoryId. GET /api/search calls it.","url":"./api/services/dump-service.ts/~/searchDumps.html","deprecated":false},{"id":"namespace_listdumps","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"listDumps","file":"api/services/dump-service.ts","doc":"Returns a page of the dumps requestingUserId may see, newest first, for the index feed (GET /api/dumps).","url":"./api/services/dump-service.ts/~/listDumps.html","deprecated":false},{"id":"namespace_listtopdumps","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"listTopDumps","file":"api/services/dump-service.ts","doc":"Returns the limit most upvoted public dumps posted from from to to, the newer first on a tie, leaving out those no one upvoted. The community service gathers them for the /community page and the digests.","url":"./api/services/dump-service.ts/~/listTopDumps.html","deprecated":false},{"id":"namespace_finddumpsbyurl","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"findDumpsByUrl","file":"api/services/dump-service.ts","doc":"Returns the dumps requestingUserId may see that were posted with the same link as url, newest first, for the create form's duplicate notice (GET /api/dumps?url=). Links are compared in their canonical form, so tracking parameters, the scheme, www. or a YouTube share format don't hide a repost.","url":"./api/services/dump-service.ts/~/findDumpsByUrl.html","deprecated":false},{"id":"namespace_updatedump","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"updateDump","file":"api/services/dump-service.ts","doc":"Applies request to a dump, for PUT /api/dumps/:dumpId. A new link has its preview fetched and gives the dump its page's title, unless request sets one. A file dump ignores url. A new slug goes through changeSlug, which exempt (a moderator) frees from its rate limit; a new title leaves the slug as it is. Clients get the dump as dump_updated, or a dump_deleted when it turns private and a dump_created when it turns public. Anyone @mentioned in the note is notified, and when it turns public, its followers are as when it is posted (notifyIfWentPublic).","url":"./api/services/dump-service.ts/~/updateDump.html","deprecated":false},{"id":"namespace_replacefiledump","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"replaceFileDump","file":"api/services/dump-service.ts","doc":"Replaces a file dump's upload and its comment, for PUT /api/dumps/:dumpId/file. A title, slug, categoryIds or isPrivate left out stays as it is. Visibility is taken here so that a new file and a change of visibility land together. The slug changes as in updateDump, before the file is written. The old file is put back if the database update fails, and clients and followers are told as updateDump tells them.","url":"./api/services/dump-service.ts/~/replaceFileDump.html","deprecated":false},{"id":"namespace_getdumpsbyuser","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getDumpsByUser","file":"api/services/dump-service.ts","doc":"Returns a page of userId's dumps, newest first, for GET /api/users/:key/dumps, optionally only those in categoryId. The route sets includePrivate when users ask for their own.","url":"./api/services/dump-service.ts/~/getDumpsByUser.html","deprecated":false},{"id":"namespace_getvoteddumpsbyuser","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getVotedDumpsByUser","file":"api/services/dump-service.ts","doc":"Returns a page of the dumps userId upvoted, latest vote first, for GET /api/users/:key/upvoted, optionally only those in categoryId. Their own private dumps are included only when they are the one asking.","url":"./api/services/dump-service.ts/~/getVotedDumpsByUser.html","deprecated":false},{"id":"namespace_refreshdumpmetadata","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"refreshDumpMetadata","file":"api/services/dump-service.ts","doc":"Fetches a URL dump's preview again, bypassing the cache, and replaces its title and preview, for POST /api/dumps/:dumpId/metadata. The slug stays.","url":"./api/services/dump-service.ts/~/refreshDumpMetadata.html","deprecated":false},{"id":"namespace_customthumbnailpath","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"customThumbnailPath","file":"api/services/dump-service.ts","doc":"Returns where dump dumpId's custom thumbnail is kept: the thumbnail route writes and serves it, and this service deletes it with the thumbnail or the dump.","url":"./api/services/dump-service.ts/~/customThumbnailPath.html","deprecated":false},{"id":"namespace_setdumpthumbnail","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"setDumpThumbnail","file":"api/services/dump-service.ts","doc":"Records that a dump has a custom thumbnail of type mime, for PUT /api/dumps/:dumpId/thumbnail, once the route has written the file.","url":"./api/services/dump-service.ts/~/setDumpThumbnail.html","deprecated":false},{"id":"namespace_removedumpthumbnail","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"removeDumpThumbnail","file":"api/services/dump-service.ts","doc":"Removes a dump's custom thumbnail and its file, for DELETE /api/dumps/:dumpId/thumbnail.","url":"./api/services/dump-service.ts/~/removeDumpThumbnail.html","deprecated":false},{"id":"namespace_deletedump","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"deleteDump","file":"api/services/dump-service.ts","doc":"Deletes a dump with its files and thumbnails, for DELETE /api/dumps/:dumpId, and broadcasts dump_deleted and the new dumps of the playlists that held it.","url":"./api/services/dump-service.ts/~/deleteDump.html","deprecated":false},{"id":"namespace_outgoingemail","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"OutgoingEmail","file":"api/services/email-service.ts","doc":"Passed to sendEmail: a rendered email, its recipient, and the headers some emails add (the digests' List-Unsubscribe).","url":"./api/services/email-service.ts/~/OutgoingEmail.html","deprecated":false},{"id":"namespace_outgoingemail","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"OutgoingEmail.to","file":"api/services/email-service.ts","doc":"","url":"./api/services/email-service.ts/~/OutgoingEmail.to.html","deprecated":false},{"id":"namespace_outgoingemail","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"OutgoingEmail.headers","file":"api/services/email-service.ts","doc":"","url":"./api/services/email-service.ts/~/OutgoingEmail.headers.html","deprecated":false},{"id":"namespace_emailtransport","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"EmailTransport","file":"api/services/email-service.ts","doc":"Hands a message to a mail server. nodemailer's SMTP transport is one, and the tests put a recording one in its place with setEmailTransport.","url":"./api/services/email-service.ts/~/EmailTransport.html","deprecated":false},{"id":"namespace_emailtransport","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"EmailTransport.sendMail","file":"api/services/email-service.ts","doc":"","url":"./api/services/email-service.ts/~/EmailTransport.sendMail.html","deprecated":false},{"id":"namespace_isemailenabled","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isEmailEnabled","file":"api/services/email-service.ts","doc":"Checks whether email can be sent. Without an SMTP server, sign-up sends no welcome email, a password reset request does nothing, and no digest goes out.","url":"./api/services/email-service.ts/~/isEmailEnabled.html","deprecated":false},{"id":"namespace_setemailtransport","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"setEmailTransport","file":"api/services/email-service.ts","doc":"Replaces the transport, so that email is enabled and every message goes to next; null disables email again. The tests use it to read what was sent.","url":"./api/services/email-service.ts/~/setEmailTransport.html","deprecated":false},{"id":"namespace_sendemail","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"sendEmail","file":"api/services/email-service.ts","doc":"Sends email from FROM_EMAIL and resolves once the SMTP server has accepted it. The welcome and reset emails don't wait for it: a slow server mustn't hold up the request.","url":"./api/services/email-service.ts/~/sendEmail.html","deprecated":false},{"id":"namespace_getpeerstatus","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getPeerStatus","file":"api/services/federation-peer-service.ts","doc":"Returns what an admin decided about the instance at issuer, or null when it is on neither list.","url":"./api/services/federation-peer-service.ts/~/getPeerStatus.html","deprecated":false},{"id":"namespace_listpeers","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"listPeers","file":"api/services/federation-peer-service.ts","doc":"Returns the instances on the lists, by name: every one for /manage, or only the trusted ones, which the login page offers.","url":"./api/services/federation-peer-service.ts/~/listPeers.html","deprecated":false},{"id":"namespace_setpeer","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"setPeer","file":"api/services/federation-peer-service.ts","doc":"Puts the instance instance names, by its API's address or its pages' (resolveIssuer), on the list of status, for /manage, and returns it. A trusted one must answer as a gerbeur instance, whose name is kept; a blocked one is blocked whether it answers or not, keeping the name it had. Blocking one ends the sessions of its users here at once: their tokens stop counting by getSessionState, and this closes their sockets.","url":"./api/services/federation-peer-service.ts/~/setPeer.html","deprecated":false},{"id":"namespace_removepeer","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"removePeer","file":"api/services/federation-peer-service.ts","doc":"Takes the instance whose host is host off the lists, for /manage: its users are invite only again, and those already here may sign in again if it was blocked.","url":"./api/services/federation-peer-service.ts/~/removePeer.html","deprecated":false},{"id":"namespace_startlogin","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"startLogin","file":"api/services/federation-service.ts","doc":"Starts a sign-in with an account on the instance request.instance names, and returns its /authorize page with the request, for POST /api/federation/logins. Unless that instance is trusted, or someone here already comes from it, the request must carry a valid invite, which is claimed only once the account is made; completeLogin makes no account without one.","url":"./api/services/federation-service.ts/~/startLogin.html","deprecated":false},{"id":"namespace_completelogin","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"completeLogin","file":"api/services/federation-service.ts","doc":"Finishes a sign-in begun by startLogin, for POST /api/federation/sessions, and returns the account it signs in to: the one linked to the identity, brought up to date, or a new one. A login works once. A new account needs the home to be trusted, or the invite the login was started with, claimed now.","url":"./api/services/federation-service.ts/~/completeLogin.html","deprecated":false},{"id":"namespace_receiveevent","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"receiveEvent","file":"api/services/federation-service.ts","doc":"Applies the signed event token from a user's home, for POST /api/federation/events: update brings their account in step, revoke ends their sessions here. Only an instance some account here comes from, and not blocked, may send one, about one of those accounts, and at most EVENT_LIMIT's rate. The sender gives up on an event at a 4xx other than 429, and tries it again later otherwise.","url":"./api/services/federation-service.ts/~/receiveEvent.html","deprecated":false},{"id":"namespace_homepageurl","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"homePageUrl","file":"api/services/federation-service.ts","doc":"Returns the URL of path on the home of user, an account from another instance, for GET /api/users/:key/home: their profile there by default, or another of its pages, such as /settings, where they change their password. A handle's host is its home's issuer, the API's origin, which needn't be its pages': those are where its /authorize page is, and the home's metadata says. While it doesn't answer, the issuer stands in.","url":"./api/services/federation-service.ts/~/homePageUrl.html","deprecated":false},{"id":"namespace_followuser","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"followUser","file":"api/services/follow-service.ts","doc":"Makes followerId follow followedUserId, and notifies the followed user. Following again changes nothing. The follower's other tabs are told.","url":"./api/services/follow-service.ts/~/followUser.html","deprecated":false},{"id":"namespace_unfollowuser","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"unfollowUser","file":"api/services/follow-service.ts","doc":"Makes followerId stop following followedUserId, if they did.","url":"./api/services/follow-service.ts/~/unfollowUser.html","deprecated":false},{"id":"namespace_followplaylist","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"followPlaylist","file":"api/services/follow-service.ts","doc":"Makes followerId follow a public playlist, and notifies its owner. Following again changes nothing. A follow outlives the playlist going private, but the feeds and lists skip it while it is.","url":"./api/services/follow-service.ts/~/followPlaylist.html","deprecated":false},{"id":"namespace_unfollowplaylist","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"unfollowPlaylist","file":"api/services/follow-service.ts","doc":"Makes followerId stop following a playlist, if they did.","url":"./api/services/follow-service.ts/~/unfollowPlaylist.html","deprecated":false},{"id":"namespace_getfollowstatus","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getFollowStatus","file":"api/services/follow-service.ts","doc":"Returns the ids of every user and playlist followerId follows, private playlists included, for GET /api/me/follow.","url":"./api/services/follow-service.ts/~/getFollowStatus.html","deprecated":false},{"id":"namespace_getfollowedusersdumpfeed","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getFollowedUsersDumpFeed","file":"api/services/follow-service.ts","doc":"Returns a page of the public dumps posted by the users followerId follows, newest first, optionally only those in categoryId. It feeds the \"users\" half of the index's \"followed\" tab.","url":"./api/services/follow-service.ts/~/getFollowedUsersDumpFeed.html","deprecated":false},{"id":"namespace_getfollowedplaylistsdumpfeed","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getFollowedPlaylistsDumpFeed","file":"api/services/follow-service.ts","doc":"Returns a page of the public dumps in the public playlists followerId follows, optionally only those in categoryId. It feeds the \"playlists\" half of the index's \"followed\" tab. A dump in several of them shows once, dated by its latest addition.","url":"./api/services/follow-service.ts/~/getFollowedPlaylistsDumpFeed.html","deprecated":false},{"id":"namespace_getfollowedplaylistsbyuser","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getFollowedPlaylistsByUser","file":"api/services/follow-service.ts","doc":"Returns a page of the public playlists userId follows, most recently followed first, for their profile and playlists pages. Their dumps are counted for requestingUserId, null being a signed-out viewer.","url":"./api/services/follow-service.ts/~/getFollowedPlaylistsByUser.html","deprecated":false},{"id":"namespace_getfollowedusersbyuser","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getFollowedUsersByUser","file":"api/services/follow-service.ts","doc":"Returns a page of the users userId follows, most recently followed first, for their profile page. The users carry their password hash and email: pass them through toPublicUser before sending them.","url":"./api/services/follow-service.ts/~/getFollowedUsersByUser.html","deprecated":false},{"id":"namespace_issuer","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"ISSUER","file":"api/services/identity-provider-service.ts","doc":"The instance's name in every token it signs and every token addressed to it: its public URL, which must be an origin for other instances to find its metadata.","url":"./api/services/identity-provider-service.ts/~/ISSUER.html","deprecated":false},{"id":"namespace_redirect_uri","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"REDIRECT_URI","file":"api/services/identity-provider-service.ts","doc":"The client's page a home instance sends the user back to, on the frontend. Its metadata announces it, and a home accepts no other.","url":"./api/services/identity-provider-service.ts/~/REDIRECT_URI.html","deprecated":false},{"id":"namespace_getinstancemetadata","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getInstanceMetadata","file":"api/services/identity-provider-service.ts","doc":"Returns the instance's metadata, served at /.well-known/openid-configuration.","url":"./api/services/identity-provider-service.ts/~/getInstanceMetadata.html","deprecated":false},{"id":"namespace_identityclaims","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"identityClaims","file":"api/services/identity-provider-service.ts","doc":"Returns what this instance tells another of user: their name, email and avatar, whose URL changes with each new one, so that a client fetches it again only then.","url":"./api/services/identity-provider-service.ts/~/identityClaims.html","deprecated":false},{"id":"namespace_describeclient","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"describeClient","file":"api/services/identity-provider-service.ts","doc":"Returns the instance clientId names, for the /authorize page's question to user userId, and whether they already let it sign them in.","url":"./api/services/identity-provider-service.ts/~/describeClient.html","deprecated":false},{"id":"namespace_createauthorizationcode","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"createAuthorizationCode","file":"api/services/identity-provider-service.ts","doc":"Records user userId's consent to sign in to the client of request, and returns where to send them: the client's callback page with a code, which the client trades within a minute (exchangeCode). The grant lasts until they withdraw it, so the page asks no more.","url":"./api/services/identity-provider-service.ts/~/createAuthorizationCode.html","deprecated":false},{"id":"namespace_exchangecode","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"exchangeCode","file":"api/services/identity-provider-service.ts","doc":"Trades a code for an identity token, for POST /api/oauth/tokens, which the client calls server to server with the form params. A code works once, within a minute, for the client and redirect it was made for, and with the verifier whose hash the request carried (PKCE). The token, signed with the instance key and addressed to the client, carries identityClaims and the request's nonce.","url":"./api/services/identity-provider-service.ts/~/exchangeCode.html","deprecated":false},{"id":"namespace_listgrants","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"listGrants","file":"api/services/identity-provider-service.ts","doc":"Returns the instances user userId let their account sign in to, the most recently used first, for the settings page.","url":"./api/services/identity-provider-service.ts/~/listGrants.html","deprecated":false},{"id":"namespace_revokegrant","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"revokeGrant","file":"api/services/identity-provider-service.ts","doc":"Withdraws user userId's grant to the instance whose host is host: it stops answering for them there, and is told to end their sessions.","url":"./api/services/identity-provider-service.ts/~/revokeGrant.html","deprecated":false},{"id":"namespace_withdrawallgrants","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"withdrawAllGrants","file":"api/services/identity-provider-service.ts","doc":"Withdraws every grant, as each user would theirs, and drops the codes not yet traded, so that no account here stays signed in elsewhere: main.ts calls it at startup when FEDERATION.outgoing is off. Returns how many grants it withdrew.","url":"./api/services/identity-provider-service.ts/~/withdrawAllGrants.html","deprecated":false},{"id":"namespace_notifyclients","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"notifyClients","file":"api/services/identity-provider-service.ts","doc":"Tells each instance user userId signed in to of event, or only those of clientIds: update when their name, email or avatar changed, revoke when their sessions there must end. The routes that change a user call it, and for an update, event may be just the type: the claims are read now. The events are queued in the outbox and their delivery starts at once, after those queued before for the same instance (deliverTo).","url":"./api/services/identity-provider-service.ts/~/notifyClients.html","deprecated":false},{"id":"namespace_deliveroutbox","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"deliverOutbox","file":"api/services/identity-provider-service.ts","doc":"Sends the outbox's events to each instance that has some, every instance at once so that one that doesn't answer delays none of the others.","url":"./api/services/identity-provider-service.ts/~/deliverOutbox.html","deprecated":false},{"id":"namespace_outboxjob","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"outboxJob","file":"api/services/identity-provider-service.ts","doc":"Retries the outbox's failed events every minute.","url":"./api/services/identity-provider-service.ts/~/outboxJob.html","deprecated":false},{"id":"namespace_getsigningkey","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getSigningKey","file":"api/services/instance-key-service.ts","doc":"Returns the key the instance signs with now: the newest stored, or a new one, stored, when there is none.","url":"./api/services/instance-key-service.ts/~/getSigningKey.html","deprecated":false},{"id":"namespace_getpublickeys","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getPublicKeys","file":"api/services/instance-key-service.ts","doc":"Returns the public halves of every stored key, for GET /.well-known/jwks.json. It makes the first key when there is none, so that the set is never empty.","url":"./api/services/instance-key-service.ts/~/getPublicKeys.html","deprecated":false},{"id":"namespace_resetsigningkey","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"resetSigningKey","file":"api/services/instance-key-service.ts","doc":"Forgets the loaded key, for the tests, which wipe the table between cases.","url":"./api/services/instance-key-service.ts/~/resetSigningKey.html","deprecated":false},{"id":"namespace_createinvite","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"createInvite","file":"api/services/invite-service.ts","doc":"Makes an invite from inviterId and returns its token, which the client puts in the invite link.","url":"./api/services/invite-service.ts/~/createInvite.html","deprecated":false},{"id":"namespace_validateinvite","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"validateInvite","file":"api/services/invite-service.ts","doc":"Returns the id of the inviter when invite token is unused and still in its window, which is the one after which db/startup.ts purges it. It doesn't claim the invite: sign-up goes through claimInvite.","url":"./api/services/invite-service.ts/~/validateInvite.html","deprecated":false},{"id":"namespace_claiminvite","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"claimInvite","file":"api/services/invite-service.ts","doc":"Marks invite token used and returns the inviter's id. Call it before the async account creation, and releaseInvite if that fails: checking first and marking after would let parallel sign-ups share one invite.","url":"./api/services/invite-service.ts/~/claimInvite.html","deprecated":false},{"id":"namespace_releaseinvite","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"releaseInvite","file":"api/services/invite-service.ts","doc":"Makes a claimed invite usable again, when the sign-up that claimed it failed.","url":"./api/services/invite-service.ts/~/releaseInvite.html","deprecated":false},{"id":"namespace_withcurrentrefs","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"withCurrentRefs","file":"api/services/notification-service.ts","doc":"Returns data with what may have changed since it was stored joined from the database: each user's current name, and the slug and owner of its dump and playlist, which the client builds their paths from. A user since deleted keeps their stored name; a deleted dump or playlist gets no ref, and so no link. Every notification the server sends goes through it, and so do the digests.","url":"./api/services/notification-service.ts/~/withCurrentRefs.html","deprecated":false},{"id":"namespace_getnotificationsforuser","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getNotificationsForUser","file":"api/services/notification-service.ts","doc":"Returns a page of userId's notifications, newest first, with their refs joined, for GET /api/me/notifications.","url":"./api/services/notification-service.ts/~/getNotificationsForUser.html","deprecated":false},{"id":"namespace_getunreadcount","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getUnreadCount","file":"api/services/notification-service.ts","doc":"Returns how many of userId's notifications are unread. The WebSocket route sends it in its welcome message, for the bell's count.","url":"./api/services/notification-service.ts/~/getUnreadCount.html","deprecated":false},{"id":"namespace_markallread","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"markAllRead","file":"api/services/notification-service.ts","doc":"Marks every notification of userId read, when they open the /notifications page, and tells all their sockets, so that the bell clears in their other tabs and devices too.","url":"./api/services/notification-service.ts/~/markAllRead.html","deprecated":false},{"id":"namespace_notifyusernewfollower","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"notifyUserNewFollower","file":"api/services/notification-service.ts","doc":"Notifies followedUserId that followerId follows them, once however often they unfollow and follow again. followUser calls it.","url":"./api/services/notification-service.ts/~/notifyUserNewFollower.html","deprecated":false},{"id":"namespace_notifyplaylistownernewfollower","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"notifyPlaylistOwnerNewFollower","file":"api/services/notification-service.ts","doc":"Notifies a playlist's owner that followerId follows it, unless they are the owner, and once however often they unfollow and follow again. followPlaylist calls it.","url":"./api/services/notification-service.ts/~/notifyPlaylistOwnerNewFollower.html","deprecated":false},{"id":"namespace_notifyuserfollowersnewdump","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"notifyUserFollowersNewDump","file":"api/services/notification-service.ts","doc":"Notifies everyone following dumperId that they posted a dump. The dump service calls it for a public dump only, when it is created or goes public. A follower is told of a dump once, however often it goes private and public again.","url":"./api/services/notification-service.ts/~/notifyUserFollowersNewDump.html","deprecated":false},{"id":"namespace_notifydumpownerupvote","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"notifyDumpOwnerUpvote","file":"api/services/notification-service.ts","doc":"Notifies a dump's poster that voterId upvoted it, unless they are the poster, and once however often the vote is withdrawn and cast again. castVote calls it.","url":"./api/services/notification-service.ts/~/notifyDumpOwnerUpvote.html","deprecated":false},{"id":"namespace_notifymentions","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"notifyMentions","file":"api/services/notification-service.ts","doc":"Notifies every user @mentioned in body, except its author, that they were mentioned in the comment, dump, playlist or chat message contextId. Call it again after each edit: a user already notified for this context isn't notified twice. skipUserId spares a mentioned user; the chat uses it for those who have it open.","url":"./api/services/notification-service.ts/~/notifyMentions.html","deprecated":false},{"id":"namespace_notifyeveryone","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"notifyEveryone","file":"api/services/notification-service.ts","doc":"Notifies every user but its author of chat message messageId, which says @everyone. The WebSocket route calls it, after notifyMentions so that a user also named is told by name, when the message is sent flagged mentionsEveryone, or when an edit flags it. Each user is notified once per message, however often it is edited. skipUserId spares the users who have the chat open, as for a mention.","url":"./api/services/notification-service.ts/~/notifyEveryone.html","deprecated":false},{"id":"namespace_notifydumpownernewcomment","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"notifyDumpOwnerNewComment","file":"api/services/notification-service.ts","doc":"Notifies a dump's poster that commenterId commented on it, unless they are the poster. createComment calls it for replies too, but not on an edit.","url":"./api/services/notification-service.ts/~/notifyDumpOwnerNewComment.html","deprecated":false},{"id":"namespace_notifycommentownerlike","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"notifyCommentOwnerLike","file":"api/services/notification-service.ts","doc":"Notifies a comment's author that likerId likes it, unless they are the author, and once however often the like is withdrawn and given again.","url":"./api/services/notification-service.ts/~/notifyCommentOwnerLike.html","deprecated":false},{"id":"namespace_notifyplaylistfollowersnewdump","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"notifyPlaylistFollowersNewDump","file":"api/services/notification-service.ts","doc":"Notifies everyone following a playlist that a dump was added to it. The playlist service calls it only when both are public, since a follower can't open a private one.","url":"./api/services/notification-service.ts/~/notifyPlaylistFollowersNewDump.html","deprecated":false},{"id":"namespace_notifyplaylistfollowersnowpublic","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"notifyPlaylistFollowersNowPublic","file":"api/services/notification-service.ts","doc":"Notifies the followers of each playlist of the dumps in it that became visible to them: a playlist's followers are told of a dump once both are public. The dump service calls it with dumpId when a dump goes public, for each public playlist holding it; the playlist service with playlistId when a playlist goes public, for each public dump in it, from the bottom of the playlist up. A dump the followers were told of before either went private isn't notified again. Adding a dump to a public playlist calls notifyPlaylistFollowersNewDump directly.","url":"./api/services/notification-service.ts/~/notifyPlaylistFollowersNowPublic.html","deprecated":false},{"id":"namespace_requestpasswordreset","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"requestPasswordReset","file":"api/services/password-reset-service.ts","doc":"Emails a reset link to the account with address email, if there is one and email is configured. It says nothing of what it did, so that the route answers the same whether the address has an account or not. It sends at most 3 links in a row per address, then one every 10 minutes.","url":"./api/services/password-reset-service.ts/~/requestPasswordReset.html","deprecated":false},{"id":"namespace_resetpassword","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"resetPassword","file":"api/services/password-reset-service.ts","doc":"Sets newPassword for the user of a reset token, marks the token used, and returns the user's id. Through updateUser, this ends the user's sessions here; the route tells the instances they signed in to.","url":"./api/services/password-reset-service.ts/~/resetPassword.html","deprecated":false},{"id":"namespace_getplaylistbyid","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getPlaylistById","file":"api/services/playlist-service.ts","doc":"Returns playlist playlistId, private or not. A caller that shows it to someone must check isPublic first, as the OG middleware does. Its dumpCount and lastDumpAt are viewerId's, or a signed-out viewer's without one.","url":"./api/services/playlist-service.ts/~/getPlaylistById.html","deprecated":false},{"id":"namespace_getplaylistbypath","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getPlaylistByPath","file":"api/services/playlist-service.ts","doc":"Returns the playlist of userId's whose slug is or was slug, private or not, or throws a 404, as getPlaylistById does, counting its dumps for viewerId likewise. Reached by a former slug, it comes with its current one.","url":"./api/services/playlist-service.ts/~/getPlaylistByPath.html","deprecated":false},{"id":"namespace_createplaylist","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"createPlaylist","file":"api/services/playlist-service.ts","doc":"Creates a playlist owned by userId, for POST /api/playlists, filed under the playlist categories req names. If it is public, it notifies the users its description mentions. It links the attachments the description embeds and broadcasts playlist_created.","url":"./api/services/playlist-service.ts/~/createPlaylist.html","deprecated":false},{"id":"namespace_getplaylist","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getPlaylist","file":"api/services/playlist-service.ts","doc":"Returns a playlist with the dumps requestingUserId may see in it, in order, for GET /api/playlists/:playlistId, and for GET /api/users/:key/playlists/:slug once it has found the playlist by its path, for the same viewer. A null requestingUserId is a signed-out viewer. Its dumpCount is the number of those dumps.","url":"./api/services/playlist-service.ts/~/getPlaylist.html","deprecated":false},{"id":"namespace_searchplaylists","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"searchPlaylists","file":"api/services/playlist-service.ts","doc":"Returns up to limit playlists whose title or description contains query, newest first, for GET /api/search, optionally only those in the playlist category categoryId. Private playlists are left out, except requestingUserId's own. A blank query finds nothing.","url":"./api/services/playlist-service.ts/~/searchPlaylists.html","deprecated":false},{"id":"namespace_listpublicplaylists","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"listPublicPlaylists","file":"api/services/playlist-service.ts","doc":"Returns a page of every public playlist, in the order sort names, for GET /api/playlists, optionally only those in the playlist category categoryId. The client's /playlists page lists them. Their dumps are counted, and so ordered, for requestingUserId, null being a signed-out viewer.","url":"./api/services/playlist-service.ts/~/listPublicPlaylists.html","deprecated":false},{"id":"namespace_listnewpublicplaylists","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"listNewPublicPlaylists","file":"api/services/playlist-service.ts","doc":"Returns the public playlists created from from to to, the fullest first and the newer on a tie. The community service gathers them for the /community page and the digests, which show every reader the same figures: only their public dumps are counted.","url":"./api/services/playlist-service.ts/~/listNewPublicPlaylists.html","deprecated":false},{"id":"namespace_listplaylistsbyuser","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"listPlaylistsByUser","file":"api/services/playlist-service.ts","doc":"Returns a page of userId's playlists, in the order sort names, for GET /api/users/:key/playlists, optionally only those in the playlist category categoryId. The private ones are listed only when requestingUserId is userId.","url":"./api/services/playlist-service.ts/~/listPlaylistsByUser.html","deprecated":false},{"id":"namespace_updateplaylist","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"updatePlaylist","file":"api/services/playlist-service.ts","doc":"Applies req to a playlist for PUT /api/playlists/:playlistId, and returns it as it now is. A new slug goes through changeSlug, first, and a moderator is exempt from its rate limit; a new title leaves the slug as it is. canModerate lets someone other than the owner edit it. If the playlist is public, it notifies, in the owner's name, the users the description mentions. When it goes public, its followers are notified of its public dumps they weren't yet told of. It links the description's attachments and tells clients of the change (broadcastPlaylistChange).","url":"./api/services/playlist-service.ts/~/updatePlaylist.html","deprecated":false},{"id":"namespace_deleteplaylist","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"deletePlaylist","file":"api/services/playlist-service.ts","doc":"Deletes a playlist for DELETE /api/playlists/:playlistId, and broadcasts playlist_deleted. canModerate lets someone other than the owner do it.","url":"./api/services/playlist-service.ts/~/deletePlaylist.html","deprecated":false},{"id":"namespace_geteditableplaylist","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getEditablePlaylist","file":"api/services/playlist-service.ts","doc":"Returns the playlist if requestingUserId may edit it. The cover upload route checks this before it writes the file, then calls setPlaylistImage.","url":"./api/services/playlist-service.ts/~/getEditablePlaylist.html","deprecated":false},{"id":"namespace_setplaylistimage","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"setPlaylistImage","file":"api/services/playlist-service.ts","doc":"Records the type of a playlist's new cover and broadcasts playlist_updated. The route must have written the file already, since clients fetch the cover as soon as they get the broadcast.","url":"./api/services/playlist-service.ts/~/setPlaylistImage.html","deprecated":false},{"id":"namespace_adddumptoplaylist","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"addDumpToPlaylist","file":"api/services/playlist-service.ts","doc":"Puts a dump at the top of a playlist, for POST /api/playlists/:playlistId/dumps/:dumpId, and broadcasts playlist_dumps_updated. The followers of a public playlist are notified when the dump is public.","url":"./api/services/playlist-service.ts/~/addDumpToPlaylist.html","deprecated":false},{"id":"namespace_removedumpfromplaylist","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"removeDumpFromPlaylist","file":"api/services/playlist-service.ts","doc":"Takes a dump out of a playlist, for DELETE /api/playlists/:playlistId/dumps/:dumpId, and broadcasts playlist_dumps_updated. A dump that isn't in it is no error.","url":"./api/services/playlist-service.ts/~/removeDumpFromPlaylist.html","deprecated":false},{"id":"namespace_reorderplaylist","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"reorderPlaylist","file":"api/services/playlist-service.ts","doc":"Puts the dumps of a playlist that the requester can see in the order of dumpIds, for PUT /api/playlists/:playlistId/order, and broadcasts playlist_dumps_updated.","url":"./api/services/playlist-service.ts/~/reorderPlaylist.html","deprecated":false},{"id":"namespace_getplaylistmembershipsfordump","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getPlaylistMembershipsForDump","file":"api/services/playlist-service.ts","doc":"Returns each of userId's playlists, newest first, and whether it holds dump dumpId, for GET /api/me/playlists?contains=. The client's add-to-playlist modal shows it.","url":"./api/services/playlist-service.ts/~/getPlaylistMembershipsForDump.html","deprecated":false},{"id":"namespace_getplaylistsfordump","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getPlaylistsForDump","file":"api/services/playlist-service.ts","doc":"Returns up to 20 playlists that hold dump dumpId, newest first, for GET /api/dumps/:dumpId/playlists. Private playlists are left out, except requestingUserId's own. The route checks first that the caller may see the dump.","url":"./api/services/playlist-service.ts/~/getPlaylistsForDump.html","deprecated":false},{"id":"namespace_getplaylistimageinfo","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getPlaylistImageInfo","file":"api/services/playlist-service.ts","doc":"Returns what GET /api/playlists/:playlistId/cover needs to serve a playlist's cover, or undefined when it has none. The route serves a private playlist's cover as private, so no shared cache keeps it.","url":"./api/services/playlist-service.ts/~/getPlaylistImageInfo.html","deprecated":false},{"id":"namespace_playlistholder","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"PlaylistHolder","file":"api/services/playlist-service.ts","doc":"A playlist holding a dump, as playlistsHolding returns it: what broadcastPlaylistDumpsUpdated needs to choose its audience.","url":"./api/services/playlist-service.ts/~/PlaylistHolder.html","deprecated":false},{"id":"namespace_playlistsholding","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"playlistsHolding","file":"api/services/playlist-service.ts","doc":"Returns the playlists holding dump dumpId. The dump service reads them before it deletes the dump or changes its visibility, and passes them to broadcastHoldersDumps after.","url":"./api/services/playlist-service.ts/~/playlistsHolding.html","deprecated":false},{"id":"namespace_broadcastholdersdumps","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"broadcastHoldersDumps","file":"api/services/playlist-service.ts","doc":"Sends each of holders its dumps again, after one of them was deleted or changed visibility, which changes what each viewer may see of them.","url":"./api/services/playlist-service.ts/~/broadcastHoldersDumps.html","deprecated":false},{"id":"namespace_fetchrichcontentresult","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"FetchRichContentResult","file":"api/services/rich-content-service.ts","doc":"Returned by tryFetchRichContent to GET /api/remote/preview, which reports ok as reached, and to refreshDumpMetadata, which gives up when it is false.","url":"./api/services/rich-content-service.ts/~/FetchRichContentResult.html","deprecated":false},{"id":"namespace_fetchrichcontentresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FetchRichContentResult.ok","file":"api/services/rich-content-service.ts","doc":"False when the page couldn't be reached at all, as opposed to reached and found to carry no metadata. A caller that already holds metadata must not overwrite it with the failure stub.","url":"./api/services/rich-content-service.ts/~/FetchRichContentResult.ok.html","deprecated":false},{"id":"namespace_fetchrichcontentresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FetchRichContentResult.content","file":"api/services/rich-content-service.ts","doc":"On failure, a stub holding the URL and its host name. Missing only when the URL doesn't parse.","url":"./api/services/rich-content-service.ts/~/FetchRichContentResult.content.html","deprecated":false},{"id":"namespace_clearrichcontentcache","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"clearRichContentCache","file":"api/services/rich-content-service.ts","doc":"Forgets every cached preview. The tests' stubNetwork calls it, since previews fetched from the previous stubbed network no longer apply.","url":"./api/services/rich-content-service.ts/~/clearRichContentCache.html","deprecated":false},{"id":"namespace_tryfetchrichcontent","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"tryFetchRichContent","file":"api/services/rich-content-service.ts","doc":"Fetches the preview of url, and says whether the page could be reached. A preview fetched in the last five minutes is reused unless fresh is set, as a metadata refresh does. It never rejects: a failure resolves to a stub.","url":"./api/services/rich-content-service.ts/~/tryFetchRichContent.html","deprecated":false},{"id":"namespace_fetchrichcontent","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"fetchRichContent","file":"api/services/rich-content-service.ts","doc":"Returns the preview of url, or a stub holding its host name when the page can't be reached. createUrlDump and updateDump use it for a new link, which has no earlier preview to keep.","url":"./api/services/rich-content-service.ts/~/fetchRichContent.html","deprecated":false},{"id":"namespace_getsettings","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getSettings","file":"api/services/settings-service.ts","doc":"Returns the settings of user userId, the defaults if they changed none.","url":"./api/services/settings-service.ts/~/getSettings.html","deprecated":false},{"id":"namespace_updatesettings","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"updateSettings","file":"api/services/settings-service.ts","doc":"Applies patch to the settings of user userId and returns them all. The settings it leaves out keep their value.","url":"./api/services/settings-service.ts/~/updateSettings.html","deprecated":false},{"id":"namespace_newslug","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"newSlug","file":"api/services/slug-service.ts","doc":"Returns a free slug for a new item of userId's titled title, for the dump and playlist services to insert it with, inside their transaction.","url":"./api/services/slug-service.ts/~/newSlug.html","deprecated":false},{"id":"namespace_resolveslug","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"resolveSlug","file":"api/services/slug-service.ts","doc":"Returns the id of userId's item of kind whose slug is or was slug, or undefined when none is.","url":"./api/services/slug-service.ts/~/resolveSlug.html","deprecated":false},{"id":"namespace_changeslug","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"changeSlug","file":"api/services/slug-service.ts","doc":"Gives item the slug slug, keeping its current one as an alias. An alias always names the item itself, so redirects never chain; taking back one of the item's own aliases swaps it with the current slug. Unless exempt (a moderator), an item's slug changes at most RENAME_LIMITS.SLUG.count times in its window, counted from its aliases. A slug equal to the current one changes nothing.","url":"./api/services/slug-service.ts/~/changeSlug.html","deprecated":false},{"id":"namespace_createuser","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"createUser","file":"api/services/user-service.ts","doc":"Creates a user with the user role, invited by inviterId, for POST /api/users. The caller has validated request and claimed the invite.","url":"./api/services/user-service.ts/~/createUser.html","deprecated":false},{"id":"namespace_createremoteuser","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"createRemoteUser","file":"api/services/user-service.ts","doc":"Creates the account of a user from another instance, named username (their handle here, name@host), with no password, for federation-service.ts, which links it to their identity there in the same transaction. inviterId is whoever invited them, or null when their instance is trusted.","url":"./api/services/user-service.ts/~/createRemoteUser.html","deprecated":false},{"id":"namespace_sendwelcomeemail","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"sendWelcomeEmail","file":"api/services/user-service.ts","doc":"Emails user the welcome message, if email is configured. The register route calls it once the account exists, and doesn't wait: a slow or failing SMTP server mustn't hold up the sign-up, so a failure is only logged.","url":"./api/services/user-service.ts/~/sendWelcomeEmail.html","deprecated":false},{"id":"namespace_getuserbyid","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getUserById","file":"api/services/user-service.ts","doc":"Returns user userId, with their hash and email.","url":"./api/services/user-service.ts/~/getUserById.html","deprecated":false},{"id":"namespace_getsessionstate","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getSessionState","file":"api/services/user-service.ts","doc":"Returns the user's live role and their last password change, before which their tokens don't count, or undefined when the user is gone, or comes from another instance while an admin blocks it or the deployment turns sign-ins from other instances off (FEDERATION.incoming). lib/auth.ts checks every session and media token against it.","url":"./api/services/user-service.ts/~/getSessionState.html","deprecated":false},{"id":"namespace_getuserbyusername","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getUserByUsername","file":"api/services/user-service.ts","doc":"Returns the user named username now, in any case, with their hash and email. Signing in takes it: a former name doesn't sign in.","url":"./api/services/user-service.ts/~/getUserByUsername.html","deprecated":false},{"id":"namespace_resolveusername","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"resolveUsername","file":"api/services/user-service.ts","doc":"Returns the user who is or was named username, in any case, or by the handle another instance gives them (localHandle): a page or an API path naming a user so reaches them, and the caller sends the client on to their current name.","url":"./api/services/user-service.ts/~/resolveUsername.html","deprecated":false},{"id":"namespace_resolveuserkey","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"resolveUserKey","file":"api/services/user-service.ts","doc":"Returns the user an API path's key names: @name by their name, current or former (resolveUsername), anything else by their id. Every route under /api/users/:key resolves its key with it.","url":"./api/services/user-service.ts/~/resolveUserKey.html","deprecated":false},{"id":"namespace_renameuser","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"renameUser","file":"api/services/user-service.ts","doc":"Renames user userId to username, for PATCH /api/users/:key/username, which only user:manage may call: users can't rename themselves. Returns them renamed. The old name becomes an alias of theirs for good, so /@old/… still reaches them and nobody else may take it; a change of case alone leaves none, since names are looked up in any case. Taking back a former name of their own is allowed. Their dumps' and playlists' slugs belong to their id, so their paths follow the new name.","url":"./api/services/user-service.ts/~/renameUser.html","deprecated":false},{"id":"namespace_setusername","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"setUsername","file":"api/services/user-service.ts","doc":"Names user userId username, keeping the old name as their alias as renameUser describes, and returns them. The caller has checked the name: renameUser checks a local one, and federation-service.ts the handle of a user renamed on their home instance.","url":"./api/services/user-service.ts/~/setUsername.html","deprecated":false},{"id":"namespace_assertlocaluser","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"assertLocalUser","file":"api/services/user-service.ts","doc":"Throws a 400 when user's account lives on another instance (isRemoteUser), whose password, email, avatar and name are that instance's to change. The routes that change them call it first.","url":"./api/services/user-service.ts/~/assertLocalUser.html","deprecated":false},{"id":"namespace_getuserbyemail","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getUserByEmail","file":"api/services/user-service.ts","doc":"Returns the local user whose email is email, in any case, or null, for requestPasswordReset. An account from another instance has no password here to reset.","url":"./api/services/user-service.ts/~/getUserByEmail.html","deprecated":false},{"id":"namespace_searchusers","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"searchUsers","file":"api/services/user-service.ts","doc":"Returns up to limit users whose name starts with query, for the editor's","url":"./api/services/user-service.ts/~/searchUsers.html","deprecated":false},{"id":"namespace_searchusersglobal","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"searchUsersGlobal","file":"api/services/user-service.ts","doc":"Returns up to limit users whose name or description contains query, for the /search page (GET /api/search). They are already public profiles.","url":"./api/services/user-service.ts/~/searchUsersGlobal.html","deprecated":false},{"id":"namespace_listnewusers","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"listNewUsers","file":"api/services/user-service.ts","doc":"Returns the users who joined from from to to, in sign-up order, each with the name of whoever invited them. The community service gathers them for the /community page and the digests.","url":"./api/services/user-service.ts/~/listNewUsers.html","deprecated":false},{"id":"namespace_updateuser","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"updateUser","file":"api/services/user-service.ts","doc":"Applies request to user userId and returns the updated user. It trusts request: the routes pick the fields a caller may change. The username changes through renameUser alone, which keeps the old one as an alias. A new password also ends every session opened before it and closes the user's sockets, so the caller must issue fresh tokens if the user is to stay signed in. A description of null keeps the current one.","url":"./api/services/user-service.ts/~/updateUser.html","deprecated":false},{"id":"namespace_revokesessions","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"revokeSessions","file":"api/services/user-service.ts","doc":"Ends every session of user userId opened before at, closing their sockets with reason: their tokens stop counting (users.tokens_valid_after, which getSessionState reads). A password change calls it, and so does the sign-out of a user from another instance, when that instance says so or an admin blocks it.","url":"./api/services/user-service.ts/~/revokeSessions.html","deprecated":false},{"id":"namespace_setuseravatar","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"setUserAvatar","file":"api/services/user-service.ts","doc":"Makes the image data user userId's avatar and returns them, for an upload (PUT /api/me/avatar) and for the avatar a user from another instance has there (federation-service.ts). Presence alone would update only the online list, so it also sends user_updated, which reaches every avatar on screen, its bumped updatedAt busting their cache.","url":"./api/services/user-service.ts/~/setUserAvatar.html","deprecated":false},{"id":"namespace_getinvitetree","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getInviteTree","file":"api/services/user-service.ts","doc":"Returns everyone userId invited, and everyone they invited in turn, eleven levels deep at most, in sign-up order, for the profile page's invite tree (GET /api/users/:key/invitees).","url":"./api/services/user-service.ts/~/getInviteTree.html","deprecated":false},{"id":"namespace_voteresult","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"VoteResult","file":"api/services/vote-service.ts","doc":"Returned to the WebSocket route by castVote and removeVote. The route acks the voter with voteCount, then broadcasts it to every client, or to the dump owner's alone when isPrivate.","url":"./api/services/vote-service.ts/~/VoteResult.html","deprecated":false},{"id":"namespace_voteresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VoteResult.voteCount","file":"api/services/vote-service.ts","doc":"","url":"./api/services/vote-service.ts/~/VoteResult.voteCount.html","deprecated":false},{"id":"namespace_voteresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VoteResult.isPrivate","file":"api/services/vote-service.ts","doc":"","url":"./api/services/vote-service.ts/~/VoteResult.isPrivate.html","deprecated":false},{"id":"namespace_castvote","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"castVote","file":"api/services/vote-service.ts","doc":"Records userId's upvote on a dump and notifies the dump's poster. The notification is best-effort: if it fails, the vote still counts.","url":"./api/services/vote-service.ts/~/castVote.html","deprecated":false},{"id":"namespace_removevote","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"removeVote","file":"api/services/vote-service.ts","doc":"Takes back userId's upvote on a dump. No visibility check: taking back a vote on a dump that has since gone private is harmless, and it's the voter's own row.","url":"./api/services/vote-service.ts/~/removeVote.html","deprecated":false},{"id":"namespace_getuservotes","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getUserVotes","file":"api/services/vote-service.ts","doc":"Returns the ids of the dumps userId upvoted. The WebSocket route sends them in its welcome message, and the client shows those vote buttons pressed.","url":"./api/services/vote-service.ts/~/getUserVotes.html","deprecated":false},{"id":"namespace_getdumpvoters","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getDumpVoters","file":"api/services/vote-service.ts","doc":"Returns a page of the users who upvoted a dump, latest vote first, for GET /api/dumps/:dumpId/voters. It doesn't check that the caller may see the dump: the route does that first, with getDump.","url":"./api/services/vote-service.ts/~/getDumpVoters.html","deprecated":false},{"id":"namespace_wsclient","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"WsClient","file":"api/services/ws-service.ts","doc":"Created by the WebSocket route for each socket it opens, and kept here until the socket closes. The user fields are read at connect and left undefined for an anonymous socket.","url":"./api/services/ws-service.ts/~/WsClient.html","deprecated":false},{"id":"namespace_wsclient","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WsClient.socket","file":"api/services/ws-service.ts","doc":"","url":"./api/services/ws-service.ts/~/WsClient.socket.html","deprecated":false},{"id":"namespace_wsclient","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WsClient.userId","file":"api/services/ws-service.ts","doc":"","url":"./api/services/ws-service.ts/~/WsClient.userId.html","deprecated":false},{"id":"namespace_wsclient","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WsClient.username","file":"api/services/ws-service.ts","doc":"","url":"./api/services/ws-service.ts/~/WsClient.username.html","deprecated":false},{"id":"namespace_wsclient","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WsClient.role","file":"api/services/ws-service.ts","doc":"Read again from the database on each chat edit or delete, so a demoted moderator loses the right at once.","url":"./api/services/ws-service.ts/~/WsClient.role.html","deprecated":false},{"id":"namespace_wsclient","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WsClient.avatarMime","file":"api/services/ws-service.ts","doc":"","url":"./api/services/ws-service.ts/~/WsClient.avatarMime.html","deprecated":false},{"id":"namespace_wsclient","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WsClient.avatarVersion","file":"api/services/ws-service.ts","doc":"Set by updateClientAvatar, for the client's avatar URLs.","url":"./api/services/ws-service.ts/~/WsClient.avatarVersion.html","deprecated":false},{"id":"namespace_wsclient","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WsClient.pongReceived","file":"api/services/ws-service.ts","doc":"Undefined until the first ping, so a new socket isn't closed at once.","url":"./api/services/ws-service.ts/~/WsClient.pongReceived.html","deprecated":false},{"id":"namespace_wsclient","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WsClient.chatOpen","file":"api/services/ws-service.ts","doc":"Set by chat_focus: the chatbox is open and the tab visible, so the user is reading the chat and gets no notification for a mention in it.","url":"./api/services/ws-service.ts/~/WsClient.chatOpen.html","deprecated":false},{"id":"namespace_wsclient","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WsClient.typingAt","file":"api/services/ws-service.ts","doc":"When the last chat_typing true arrived, in ms.","url":"./api/services/ws-service.ts/~/WsClient.typingAt.html","deprecated":false},{"id":"namespace_register","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"register","file":"api/services/ws-service.ts","doc":"Adds a client once its socket opens. From then on, it receives the broadcasts, and is shown online if it is signed in.","url":"./api/services/ws-service.ts/~/register.html","deprecated":false},{"id":"namespace_unregister","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"unregister","file":"api/services/ws-service.ts","doc":"Removes a client when its socket closes. The caller rebroadcasts presence.","url":"./api/services/ws-service.ts/~/unregister.html","deprecated":false},{"id":"namespace_updateclientavatar","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"updateClientAvatar","file":"api/services/ws-service.ts","doc":"Records userId's new avatar on their clients, so presence and the typing list show it, and rebroadcasts presence. routes/avatars.ts calls it on an upload.","url":"./api/services/ws-service.ts/~/updateClientAvatar.html","deprecated":false},{"id":"namespace_updateclientusername","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"updateClientUsername","file":"api/services/ws-service.ts","doc":"Records userId's new name on their clients, so presence and the typing list show it, and rebroadcasts presence. The routes that rename a user call it, along with broadcastUserUpdated.","url":"./api/services/ws-service.ts/~/updateClientUsername.html","deprecated":false},{"id":"namespace_getonlineusers","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getOnlineUsers","file":"api/services/ws-service.ts","doc":"Returns each signed-in user with a socket open, once. The route sends it in welcome, and broadcastPresence in presence_update.","url":"./api/services/ws-service.ts/~/getOnlineUsers.html","deprecated":false},{"id":"namespace_send","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"send","file":"api/services/ws-service.ts","doc":"Sends data to one socket unless it is closing. The WebSocket route answers a client's own message with it: a pong, a vote's ack, an error.","url":"./api/services/ws-service.ts/~/send.html","deprecated":false},{"id":"namespace_sendtouser","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"sendToUser","file":"api/services/ws-service.ts","doc":"Sends data to every socket of userId. The notification service sends notification_created and notifications_read with it, the follow service follows_changed, and the route chat_read_update.","url":"./api/services/ws-service.ts/~/sendToUser.html","deprecated":false},{"id":"namespace_closeusersockets","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"closeUserSockets","file":"api/services/ws-service.ts","doc":"Closes every socket of userId without signing anyone out. The user service calls it on a password change. Each tab reconnects with the token it holds: the tab that made the change has a fresh one and stays signed in, while the others connect anonymously and sign out on their next 401.","url":"./api/services/ws-service.ts/~/closeUserSockets.html","deprecated":false},{"id":"namespace_broadcastpresence","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"broadcastPresence","file":"api/services/ws-service.ts","doc":"Sends everyone presence_update. The route calls it whenever a socket opens or closes.","url":"./api/services/ws-service.ts/~/broadcastPresence.html","deprecated":false},{"id":"namespace_broadcastdumpchange","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"broadcastDumpChange","file":"api/services/ws-service.ts","doc":"Tells the clients that may see a dump how it changed, as broadcastChange says, for the dump service after every write.","url":"./api/services/ws-service.ts/~/broadcastDumpChange.html","deprecated":false},{"id":"namespace_broadcastdumprelatedchanged","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"broadcastDumpRelatedChanged","file":"api/services/ws-service.ts","doc":"Sends dump_related_changed after the links between dump and each of others changed, for the backlink service. A link shows only to those who may see both its ends, so a socket is told only when its user may see dump and one of others, and of those alone.","url":"./api/services/ws-service.ts/~/broadcastDumpRelatedChanged.html","deprecated":false},{"id":"namespace_broadcastvoteupdate","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"broadcastVoteUpdate","file":"api/services/ws-service.ts","doc":"Sends votes_update after the route stored a vote, to everyone, or with onlyUserId to that user's sockets alone (for a private dump).","url":"./api/services/ws-service.ts/~/broadcastVoteUpdate.html","deprecated":false},{"id":"namespace_broadcastcommentlikeupdate","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"broadcastCommentLikeUpdate","file":"api/services/ws-service.ts","doc":"Sends comment_likes_update after the route stored a like, to everyone, or with onlyUserId to that user's sockets alone (for a comment on a private dump).","url":"./api/services/ws-service.ts/~/broadcastCommentLikeUpdate.html","deprecated":false},{"id":"namespace_broadcastplaylistchange","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"broadcastPlaylistChange","file":"api/services/ws-service.ts","doc":"Tells the clients that may see a playlist how it changed, as broadcastChange says, for the playlist service after every write to its details. A playlist turned private thus leaves the others' views without their learning what it became. members are the dumps of after: each socket gets the playlist with the count of those its user may see and the date of the latest, the owner's private dumps being theirs alone to count.","url":"./api/services/ws-service.ts/~/broadcastPlaylistChange.html","deprecated":false},{"id":"namespace_broadcastplaylistdumpsupdated","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"broadcastPlaylistDumpsUpdated","file":"api/services/ws-service.ts","doc":"Sends playlist_dumps_updated to the playlist's audience, each socket with only the dumps its user may see, as GET would list them. The private dumps in a public playlist stay hidden from everyone but their posters, and so does their number: a client counts the dumps it is sent.","url":"./api/services/ws-service.ts/~/broadcastPlaylistDumpsUpdated.html","deprecated":false},{"id":"namespace_broadcastuserupdated","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"broadcastUserUpdated","file":"api/services/ws-service.ts","doc":"Sends everyone user_updated, after a profile edit, a role change or an avatar upload.","url":"./api/services/ws-service.ts/~/broadcastUserUpdated.html","deprecated":false},{"id":"namespace_broadcastcommentcreated","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"broadcastCommentCreated","file":"api/services/ws-service.ts","doc":"Sends comment_created to those who may see the comment's dump: everyone, or its owner alone when it is private. The comments route calls it, as it does the two below.","url":"./api/services/ws-service.ts/~/broadcastCommentCreated.html","deprecated":false},{"id":"namespace_broadcastcommentdeleted","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"broadcastCommentDeleted","file":"api/services/ws-service.ts","doc":"Sends comment_deleted, as broadcastCommentCreated does.","url":"./api/services/ws-service.ts/~/broadcastCommentDeleted.html","deprecated":false},{"id":"namespace_broadcastcommentupdated","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"broadcastCommentUpdated","file":"api/services/ws-service.ts","doc":"Sends comment_updated, as broadcastCommentCreated does.","url":"./api/services/ws-service.ts/~/broadcastCommentUpdated.html","deprecated":false},{"id":"namespace_broadcastcategorieschanged","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"broadcastCategoriesChanged","file":"api/services/ws-service.ts","doc":"Sends everyone categories_changed, after the category manager created, edited or deleted one, so that every client fetches them again.","url":"./api/services/ws-service.ts/~/broadcastCategoriesChanged.html","deprecated":false},{"id":"namespace_broadcastchatmessage","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"broadcastChatMessage","file":"api/services/ws-service.ts","doc":"Sends chat_message to every signed-in socket, the sender's included. nonce comes from the sender's chat_send, and lets it swap its pending copy for the message.","url":"./api/services/ws-service.ts/~/broadcastChatMessage.html","deprecated":false},{"id":"namespace_broadcastchatmessageupdated","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"broadcastChatMessageUpdated","file":"api/services/ws-service.ts","doc":"Sends chat_message_updated to every signed-in socket.","url":"./api/services/ws-service.ts/~/broadcastChatMessageUpdated.html","deprecated":false},{"id":"namespace_broadcastchatmessagedeleted","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"broadcastChatMessageDeleted","file":"api/services/ws-service.ts","doc":"Sends chat_message_deleted to every signed-in socket.","url":"./api/services/ws-service.ts/~/broadcastChatMessageDeleted.html","deprecated":false},{"id":"namespace_gettypingusers","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"getTypingUsers","file":"api/services/ws-service.ts","doc":"Returns each user who sent chat_typing true within the last TYPING_TTL, once, for broadcastTyping.","url":"./api/services/ws-service.ts/~/getTypingUsers.html","deprecated":false},{"id":"namespace_broadcasttyping","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"broadcastTyping","file":"api/services/ws-service.ts","doc":"Sends chat_typing_update to every signed-in socket. The route also calls it when a typing user's socket closes.","url":"./api/services/ws-service.ts/~/broadcastTyping.html","deprecated":false},{"id":"namespace_setclienttyping","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"setClientTyping","file":"api/services/ws-service.ts","doc":"Records a client's chat_typing, and broadcasts the typing list when the client starts or stops. The route also clears it when the client sends a message. A client that stops without saying so is expired after TYPING_TTL.","url":"./api/services/ws-service.ts/~/setClientTyping.html","deprecated":false},{"id":"namespace_typingexpiryjob","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"typingExpiryJob","file":"api/services/ws-service.ts","doc":"Expires the typing users who went quiet without a false, such as by closing the tab, every 2 seconds. main.ts starts it.","url":"./api/services/ws-service.ts/~/typingExpiryJob.html","deprecated":false},{"id":"namespace_isuserchatopen","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isUserChatOpen","file":"api/services/ws-service.ts","doc":"Checks whether userId is reading the chat on any of their sockets. The route passes it to notifyMentions, which skips those users: they saw the mention live, and their client chimes for it.","url":"./api/services/ws-service.ts/~/isUserChatOpen.html","deprecated":false},{"id":"namespace_handleclientpong","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"handleClientPong","file":"api/services/ws-service.ts","doc":"Records a client's pong, which keeps its socket open.","url":"./api/services/ws-service.ts/~/handleClientPong.html","deprecated":false},{"id":"namespace_pingjob","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"pingJob","file":"api/services/ws-service.ts","doc":"Pings every client each PING_INTERVAL, closing the ones that didn't answer the previous ping. main.ts starts it.","url":"./api/services/ws-service.ts/~/pingJob.html","deprecated":false},{"id":"namespace_iscreatecategoryrequest","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isCreateCategoryRequest","file":"api/validators/category.ts","doc":"Checks whether obj has the fields of a CreateCategoryRequest.","url":"./api/validators/category.ts/~/isCreateCategoryRequest.html","deprecated":false},{"id":"namespace_isupdatecategoryrequest","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isUpdateCategoryRequest","file":"api/validators/category.ts","doc":"Checks whether obj has the fields of an UpdateCategoryRequest.","url":"./api/validators/category.ts/~/isUpdateCategoryRequest.html","deprecated":false},{"id":"namespace_iscreatecommentrequest","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isCreateCommentRequest","file":"api/validators/comment.ts","doc":"Checks whether obj is a CreateCommentRequest whose body isn't blank and fits VALIDATION.COMMENT_BODY_MAX. A null parentId passes, as a top-level comment.","url":"./api/validators/comment.ts/~/isCreateCommentRequest.html","deprecated":false},{"id":"namespace_isupdatecommentrequest","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isUpdateCommentRequest","file":"api/validators/comment.ts","doc":"Checks whether obj is an UpdateCommentRequest whose body isn't blank and fits VALIDATION.COMMENT_BODY_MAX.","url":"./api/validators/comment.ts/~/isUpdateCommentRequest.html","deprecated":false},{"id":"namespace_iscreateurldumprequest","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isCreateUrlDumpRequest","file":"api/validators/dump.ts","doc":"Checks whether obj is a CreateUrlDumpRequest whose title and comment fit the VALIDATION limits. It leaves the URL to createUrlDump, which rejects anything but a public http(s) URL.","url":"./api/validators/dump.ts/~/isCreateUrlDumpRequest.html","deprecated":false},{"id":"namespace_isupdatedumprequest","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isUpdateDumpRequest","file":"api/validators/dump.ts","doc":"Checks whether obj is an UpdateDumpRequest whose title and comment fit the VALIDATION limits. Unlike on creation, a title that is given must not be blank.","url":"./api/validators/dump.ts/~/isUpdateDumpRequest.html","deprecated":false},{"id":"namespace_parsecategoryids","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"parseCategoryIds","file":"api/validators/dump.ts","doc":"Parses a multipart form's categoryIds, a JSON array sent as a string. A missing or malformed value counts as no category. The dumps and files routes read the forms that post and replace a file with it.","url":"./api/validators/dump.ts/~/parseCategoryIds.html","deprecated":false},{"id":"namespace_isfederationloginrequest","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isFederationLoginRequest","file":"api/validators/federation.ts","doc":"Checks whether obj is a FederationLoginRequest.","url":"./api/validators/federation.ts/~/isFederationLoginRequest.html","deprecated":false},{"id":"namespace_isfederationsessionrequest","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isFederationSessionRequest","file":"api/validators/federation.ts","doc":"Checks whether obj is a FederationSessionRequest.","url":"./api/validators/federation.ts/~/isFederationSessionRequest.html","deprecated":false},{"id":"namespace_isauthorizerequest","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isAuthorizeRequest","file":"api/validators/federation.ts","doc":"Checks whether obj is an AuthorizeRequest.","url":"./api/validators/federation.ts/~/isAuthorizeRequest.html","deprecated":false},{"id":"namespace_issetpeerrequest","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isSetPeerRequest","file":"api/validators/federation.ts","doc":"Checks whether obj is a SetPeerRequest.","url":"./api/validators/federation.ts/~/isSetPeerRequest.html","deprecated":false},{"id":"namespace_iscreateplaylistrequest","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isCreatePlaylistRequest","file":"api/validators/playlist.ts","doc":"Checks whether obj is a CreatePlaylistRequest with a title that isn't blank, and a title and description within the VALIDATION limits. A null description passes. Whether its category ids name playlist categories is the playlist service's to check.","url":"./api/validators/playlist.ts/~/isCreatePlaylistRequest.html","deprecated":false},{"id":"namespace_isupdateplaylistrequest","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isUpdatePlaylistRequest","file":"api/validators/playlist.ts","doc":"Checks whether obj is an UpdatePlaylistRequest whose title, if given, isn't blank, with a title and description within the VALIDATION limits.","url":"./api/validators/playlist.ts/~/isUpdatePlaylistRequest.html","deprecated":false},{"id":"namespace_isreorderplaylistrequest","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isReorderPlaylistRequest","file":"api/validators/playlist.ts","doc":"Checks whether obj is a ReorderPlaylistRequest. Whether its ids match the playlist is reorderPlaylist's to check.","url":"./api/validators/playlist.ts/~/isReorderPlaylistRequest.html","deprecated":false},{"id":"namespace_isupdatesettingsrequest","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isUpdateSettingsRequest","file":"api/validators/settings.ts","doc":"Checks whether obj is an UpdateSettingsRequest: an object whose every key is a setting, each with a value that setting takes. An unknown key fails, so a typo doesn't pass for a change.","url":"./api/validators/settings.ts/~/isUpdateSettingsRequest.html","deprecated":false},{"id":"namespace_isloginuserrequest","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isLoginUserRequest","file":"api/validators/user.ts","doc":"Checks whether obj is a LoginUserRequest. It checks the types only: a wrong name or password is the login route's answer to give.","url":"./api/validators/user.ts/~/isLoginUserRequest.html","deprecated":false},{"id":"namespace_fieldof","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"fieldOf","file":"api/validators/user.ts","doc":"Returns obj[key] when obj is an object that has it, else undefined. The users routes whose body has no guard of its own read their fields with it.","url":"./api/validators/user.ts/~/fieldOf.html","deprecated":false},{"id":"namespace_isregisteruserrequest","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isRegisterUserRequest","file":"api/validators/user.ts","doc":"Checks whether obj is a valid RegisterUserRequest. When it isn't, validateRegisterUserRequest says why.","url":"./api/validators/user.ts/~/isRegisterUserRequest.html","deprecated":false},{"id":"namespace_validateregisteruserrequest","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"validateRegisterUserRequest","file":"api/validators/user.ts","doc":"Returns what is wrong with a sign-up body, as the message the register page shows, or null when it is valid. It checks the shape, the email's form, and the username and password against the VALIDATION limits. Whether the name, the email or the invite is taken is createUser's and claimInvite's check.","url":"./api/validators/user.ts/~/validateRegisterUserRequest.html","deprecated":false},{"id":"namespace_isupdateuserrequest","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isUpdateUserRequest","file":"api/validators/user.ts","doc":"Checks whether obj is a valid UpdateUserRequest, for PATCH /api/me. Every field is optional, but each one present must be well-formed and within the VALIDATION limits.","url":"./api/validators/user.ts/~/isUpdateUserRequest.html","deprecated":false},{"id":"namespace_devinstance","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"DevInstance","file":"dev/instances.ts","doc":"One instance of INSTANCES.","url":"./dev/instances.ts/~/DevInstance.html","deprecated":false},{"id":"namespace_devinstance","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DevInstance.name","file":"dev/instances.ts","doc":"Names its database and uploads, and prefixes its output. Lowercase letters, digits and hyphens.","url":"./dev/instances.ts/~/DevInstance.name.html","deprecated":false},{"id":"namespace_devinstance","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DevInstance.apiPort","file":"dev/instances.ts","doc":"The port of its API server, GERBEUR_PORT.","url":"./dev/instances.ts/~/DevInstance.apiPort.html","deprecated":false},{"id":"namespace_devinstance","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DevInstance.webPort","file":"dev/instances.ts","doc":"The port of its Vite server, where its pages are.","url":"./dev/instances.ts/~/DevInstance.webPort.html","deprecated":false},{"id":"namespace_devinstance","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DevInstance.env","file":"dev/instances.ts","doc":"GERBEUR_* settings of its own, over the base .env: a site name, an emoji or a style, to tell the instances apart, or which ways federated sign-in goes.","url":"./dev/instances.ts/~/DevInstance.env.html","deprecated":false},{"id":"namespace_instances","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"INSTANCES","file":"dev/instances.ts","doc":"The instances deno task dev starts, in this order. The first keeps the ports the single dev server always had, and takes no users of the others, while its own sign in to them, so that both switches of federated sign-in can be tried.","url":"./dev/instances.ts/~/INSTANCES.html","deprecated":false},{"id":"namespace_apierrorcode","kind":[{"char":"v","kind":"Variable","title":"Variable"},{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"APIErrorCode","file":"shared/api.ts","doc":"Lists the codes an APIError carries, one per HTTP status. The backend's APIException derives its code from the status it is given, and the frontend shows the message without reading the code.","url":"./shared/api.ts/~/APIErrorCode.html","deprecated":false},{"id":"namespace_apierrorcode","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"APIErrorCode.BAD_REQUEST","file":"shared/api.ts","doc":"","url":"./shared/api.ts/~/APIErrorCode.BAD_REQUEST.html","deprecated":false},{"id":"namespace_apierrorcode","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"APIErrorCode.UNAUTHORIZED","file":"shared/api.ts","doc":"","url":"./shared/api.ts/~/APIErrorCode.UNAUTHORIZED.html","deprecated":false},{"id":"namespace_apierrorcode","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"APIErrorCode.FORBIDDEN","file":"shared/api.ts","doc":"","url":"./shared/api.ts/~/APIErrorCode.FORBIDDEN.html","deprecated":false},{"id":"namespace_apierrorcode","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"APIErrorCode.NOT_FOUND","file":"shared/api.ts","doc":"Also answers for what exists but the caller may not see.","url":"./shared/api.ts/~/APIErrorCode.NOT_FOUND.html","deprecated":false},{"id":"namespace_apierrorcode","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"APIErrorCode.CONFLICT","file":"shared/api.ts","doc":"","url":"./shared/api.ts/~/APIErrorCode.CONFLICT.html","deprecated":false},{"id":"namespace_apierrorcode","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"APIErrorCode.RATE_LIMITED","file":"shared/api.ts","doc":"","url":"./shared/api.ts/~/APIErrorCode.RATE_LIMITED.html","deprecated":false},{"id":"namespace_apierrorcode","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"APIErrorCode.SERVER_ERROR","file":"shared/api.ts","doc":"","url":"./shared/api.ts/~/APIErrorCode.SERVER_ERROR.html","deprecated":false},{"id":"namespace_apierrorcode","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"APIErrorCode.BAD_GATEWAY","file":"shared/api.ts","doc":"Answers when another site, such as Bandcamp or YouTube, failed us.","url":"./shared/api.ts/~/APIErrorCode.BAD_GATEWAY.html","deprecated":false},{"id":"namespace_apierror","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"APIError","file":"shared/api.ts","doc":"Sent in an APIFailure. The frontend shows message to the user, so it is written for them.","url":"./shared/api.ts/~/APIError.html","deprecated":false},{"id":"namespace_apierror","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"APIError.code","file":"shared/api.ts","doc":"","url":"./shared/api.ts/~/APIError.code.html","deprecated":false},{"id":"namespace_apierror","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"APIError.message","file":"shared/api.ts","doc":"","url":"./shared/api.ts/~/APIError.message.html","deprecated":false},{"id":"namespace_apisuccess","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"APISuccess","file":"shared/api.ts","doc":"Sent by a route that succeeded, around its payload.","url":"./shared/api.ts/~/APISuccess.html","deprecated":false},{"id":"namespace_apisuccess","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"APISuccess.success","file":"shared/api.ts","doc":"","url":"./shared/api.ts/~/APISuccess.success.html","deprecated":false},{"id":"namespace_apisuccess","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"APISuccess.data","file":"shared/api.ts","doc":"","url":"./shared/api.ts/~/APISuccess.data.html","deprecated":false},{"id":"namespace_apisuccess","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"APISuccess.error","file":"shared/api.ts","doc":"","url":"./shared/api.ts/~/APISuccess.error.html","deprecated":false},{"id":"namespace_apifailure","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"APIFailure","file":"shared/api.ts","doc":"Sent by the error middleware when a request fails, and by the few routes that answer an error themselves.","url":"./shared/api.ts/~/APIFailure.html","deprecated":false},{"id":"namespace_apifailure","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"APIFailure.success","file":"shared/api.ts","doc":"","url":"./shared/api.ts/~/APIFailure.success.html","deprecated":false},{"id":"namespace_apifailure","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"APIFailure.data","file":"shared/api.ts","doc":"","url":"./shared/api.ts/~/APIFailure.data.html","deprecated":false},{"id":"namespace_apifailure","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"APIFailure.error","file":"shared/api.ts","doc":"","url":"./shared/api.ts/~/APIFailure.error.html","deprecated":false},{"id":"namespace_apiresponse","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"APIResponse","file":"shared/api.ts","doc":"Returned by every JSON endpoint. A reader tells the two apart by success.","url":"./shared/api.ts/~/APIResponse.html","deprecated":false},{"id":"namespace_paginateddata","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PaginatedData","file":"shared/api.ts","doc":"Returned by the list endpoints, as the data of an APISuccess.","url":"./shared/api.ts/~/PaginatedData.html","deprecated":false},{"id":"namespace_paginateddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PaginatedData.items","file":"shared/api.ts","doc":"","url":"./shared/api.ts/~/PaginatedData.items.html","deprecated":false},{"id":"namespace_paginateddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PaginatedData.hasMore","file":"shared/api.ts","doc":"","url":"./shared/api.ts/~/PaginatedData.hasMore.html","deprecated":false},{"id":"namespace_paginateddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PaginatedData.total","file":"shared/api.ts","doc":"The size of the whole list, set only by search, which shows it.","url":"./shared/api.ts/~/PaginatedData.total.html","deprecated":false},{"id":"namespace_wire","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"Wire","file":"shared/api.ts","doc":"T as the client reads it from JSON, over HTTP, the socket or localStorage, where every Date has become an ISO string.","url":"./shared/api.ts/~/Wire.html","deprecated":false},{"id":"namespace_attachmentresponse","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"AttachmentResponse","file":"shared/attachment.ts","doc":"Returned by POST /api/attachments to the text editor, which inserts the image into the body as a link to attachmentPath.","url":"./shared/attachment.ts/~/AttachmentResponse.html","deprecated":false},{"id":"namespace_attachmentresponse","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AttachmentResponse.id","file":"shared/attachment.ts","doc":"","url":"./shared/attachment.ts/~/AttachmentResponse.id.html","deprecated":false},{"id":"namespace_attachmentpath","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"attachmentPath","file":"shared/attachment.ts","doc":"Returns the API path of attachment id, to which the API's base is added.","url":"./shared/attachment.ts/~/attachmentPath.html","deprecated":false},{"id":"namespace_attachmentidsin","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"attachmentIdsIn","file":"shared/attachment.ts","doc":"Returns the ids of the attachments text links to, in order.","url":"./shared/attachment.ts/~/attachmentIdsIn.html","deprecated":false},{"id":"namespace_isattachmenturl","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isAttachmentUrl","file":"shared/attachment.ts","doc":"Checks whether url is an attachment's, with no query yet.","url":"./shared/attachment.ts/~/isAttachmentUrl.html","deprecated":false},{"id":"namespace_category_kinds","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"CATEGORY_KINDS","file":"shared/category.ts","doc":"Lists what a category files: a dump category files dumps, a playlist category playlists. Each kind is a set of its own, whose slugs and names are unique within it.","url":"./shared/category.ts/~/CATEGORY_KINDS.html","deprecated":false},{"id":"namespace_categorykind","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"CategoryKind","file":"shared/category.ts","doc":"One of the CATEGORY_KINDS.","url":"./shared/category.ts/~/CategoryKind.html","deprecated":false},{"id":"namespace_iscategorykind","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isCategoryKind","file":"shared/category.ts","doc":"Checks whether value is one of the CATEGORY_KINDS, for the category validator and the rows the category service reads.","url":"./shared/category.ts/~/isCategoryKind.html","deprecated":false},{"id":"namespace_category","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"Category","file":"shared/category.ts","doc":"Returned by the category routes. A dump category's feed lives at /<slug> on the client, a playlist category's at /playlists/<slug>, and a dump or playlist names its categories by id in categoryIds.","url":"./shared/category.ts/~/Category.html","deprecated":false},{"id":"namespace_category","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Category.id","file":"shared/category.ts","doc":"","url":"./shared/category.ts/~/Category.id.html","deprecated":false},{"id":"namespace_category","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Category.kind","file":"shared/category.ts","doc":"What it files. It never changes.","url":"./shared/category.ts/~/Category.kind.html","deprecated":false},{"id":"namespace_category","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Category.slug","file":"shared/category.ts","doc":"","url":"./shared/category.ts/~/Category.slug.html","deprecated":false},{"id":"namespace_category","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Category.name","file":"shared/category.ts","doc":"","url":"./shared/category.ts/~/Category.name.html","deprecated":false},{"id":"namespace_category","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Category.position","file":"shared/category.ts","doc":"Sorts the categories, lowest first.","url":"./shared/category.ts/~/Category.position.html","deprecated":false},{"id":"namespace_category","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Category.createdAt","file":"shared/category.ts","doc":"","url":"./shared/category.ts/~/Category.createdAt.html","deprecated":false},{"id":"namespace_category","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Category.updatedAt","file":"shared/category.ts","doc":"","url":"./shared/category.ts/~/Category.updatedAt.html","deprecated":false},{"id":"namespace_createcategoryrequest","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CreateCategoryRequest","file":"shared/category.ts","doc":"Passed to POST /api/categories. The slug must be free within its kind, and a dump category's not reserved by a route.","url":"./shared/category.ts/~/CreateCategoryRequest.html","deprecated":false},{"id":"namespace_createcategoryrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CreateCategoryRequest.kind","file":"shared/category.ts","doc":"","url":"./shared/category.ts/~/CreateCategoryRequest.kind.html","deprecated":false},{"id":"namespace_createcategoryrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CreateCategoryRequest.slug","file":"shared/category.ts","doc":"","url":"./shared/category.ts/~/CreateCategoryRequest.slug.html","deprecated":false},{"id":"namespace_createcategoryrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CreateCategoryRequest.name","file":"shared/category.ts","doc":"","url":"./shared/category.ts/~/CreateCategoryRequest.name.html","deprecated":false},{"id":"namespace_createcategoryrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CreateCategoryRequest.position","file":"shared/category.ts","doc":"0 when left out.","url":"./shared/category.ts/~/CreateCategoryRequest.position.html","deprecated":false},{"id":"namespace_updatecategoryrequest","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UpdateCategoryRequest","file":"shared/category.ts","doc":"Passed to PUT /api/categories/:id. A field left out keeps its value, and the kind is kept.","url":"./shared/category.ts/~/UpdateCategoryRequest.html","deprecated":false},{"id":"namespace_updatecategoryrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UpdateCategoryRequest.slug","file":"shared/category.ts","doc":"","url":"./shared/category.ts/~/UpdateCategoryRequest.slug.html","deprecated":false},{"id":"namespace_updatecategoryrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UpdateCategoryRequest.name","file":"shared/category.ts","doc":"","url":"./shared/category.ts/~/UpdateCategoryRequest.name.html","deprecated":false},{"id":"namespace_updatecategoryrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UpdateCategoryRequest.position","file":"shared/category.ts","doc":"","url":"./shared/category.ts/~/UpdateCategoryRequest.position.html","deprecated":false},{"id":"namespace_chatmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ChatMessage","file":"shared/chat.ts","doc":"Returned by GET /api/chat, and sent by the server in chat_message and chat_message_updated. The client reads it through deserializeChatMessage, which turns its dates back into Dates.","url":"./shared/chat.ts/~/ChatMessage.html","deprecated":false},{"id":"namespace_chatmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessage.id","file":"shared/chat.ts","doc":"","url":"./shared/chat.ts/~/ChatMessage.id.html","deprecated":false},{"id":"namespace_chatmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessage.userId","file":"shared/chat.ts","doc":"","url":"./shared/chat.ts/~/ChatMessage.userId.html","deprecated":false},{"id":"namespace_chatmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessage.body","file":"shared/chat.ts","doc":"In Markdown, trimmed by the server.","url":"./shared/chat.ts/~/ChatMessage.body.html","deprecated":false},{"id":"namespace_chatmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessage.createdAt","file":"shared/chat.ts","doc":"","url":"./shared/chat.ts/~/ChatMessage.createdAt.html","deprecated":false},{"id":"namespace_chatmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessage.updatedAt","file":"shared/chat.ts","doc":"Absent until the first edit.","url":"./shared/chat.ts/~/ChatMessage.updatedAt.html","deprecated":false},{"id":"namespace_chatmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessage.authorUsername","file":"shared/chat.ts","doc":"","url":"./shared/chat.ts/~/ChatMessage.authorUsername.html","deprecated":false},{"id":"namespace_chatmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessage.authorAvatarMime","file":"shared/chat.ts","doc":"","url":"./shared/chat.ts/~/ChatMessage.authorAvatarMime.html","deprecated":false},{"id":"namespace_chatmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessage.replyToId","file":"shared/chat.ts","doc":"Kept when the message it points to is deleted, while replyToAuthor and replyToBody then go absent.","url":"./shared/chat.ts/~/ChatMessage.replyToId.html","deprecated":false},{"id":"namespace_chatmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessage.replyToAuthor","file":"shared/chat.ts","doc":"","url":"./shared/chat.ts/~/ChatMessage.replyToAuthor.html","deprecated":false},{"id":"namespace_chatmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessage.replyToBody","file":"shared/chat.ts","doc":"The first 300 characters of the replied-to body, in Markdown.","url":"./shared/chat.ts/~/ChatMessage.replyToBody.html","deprecated":false},{"id":"namespace_chatmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessage.mentionsEveryone","file":"shared/chat.ts","doc":"Set when the body says @everyone and its author's role had chat:everyone when it was last written; absent otherwise. The client highlights the message for everyone and shows @everyone as a mention by it, never by the text, which anyone may type.","url":"./shared/chat.ts/~/ChatMessage.mentionsEveryone.html","deprecated":false},{"id":"namespace_comment","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"Comment","file":"shared/comment.ts","doc":"Returned by the comment routes, and sent in the comment_created and comment_updated WebSocket messages. It carries its author's name and avatar, so the thread needn't look them up.","url":"./shared/comment.ts/~/Comment.html","deprecated":false},{"id":"namespace_comment","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Comment.id","file":"shared/comment.ts","doc":"","url":"./shared/comment.ts/~/Comment.id.html","deprecated":false},{"id":"namespace_comment","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Comment.dumpId","file":"shared/comment.ts","doc":"","url":"./shared/comment.ts/~/Comment.dumpId.html","deprecated":false},{"id":"namespace_comment","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Comment.userId","file":"shared/comment.ts","doc":"","url":"./shared/comment.ts/~/Comment.userId.html","deprecated":false},{"id":"namespace_comment","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Comment.parentId","file":"shared/comment.ts","doc":"It is undefined on a top-level comment.","url":"./shared/comment.ts/~/Comment.parentId.html","deprecated":false},{"id":"namespace_comment","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Comment.body","file":"shared/comment.ts","doc":"The Markdown text. Deleting the comment empties it.","url":"./shared/comment.ts/~/Comment.body.html","deprecated":false},{"id":"namespace_comment","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Comment.createdAt","file":"shared/comment.ts","doc":"","url":"./shared/comment.ts/~/Comment.createdAt.html","deprecated":false},{"id":"namespace_comment","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Comment.updatedAt","file":"shared/comment.ts","doc":"","url":"./shared/comment.ts/~/Comment.updatedAt.html","deprecated":false},{"id":"namespace_comment","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Comment.deleted","file":"shared/comment.ts","doc":"A deleted comment stays in the thread, emptied, so its replies keep their place.","url":"./shared/comment.ts/~/Comment.deleted.html","deprecated":false},{"id":"namespace_comment","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Comment.likeCount","file":"shared/comment.ts","doc":"","url":"./shared/comment.ts/~/Comment.likeCount.html","deprecated":false},{"id":"namespace_comment","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Comment.authorUsername","file":"shared/comment.ts","doc":"","url":"./shared/comment.ts/~/Comment.authorUsername.html","deprecated":false},{"id":"namespace_comment","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Comment.authorAvatarMime","file":"shared/comment.ts","doc":"","url":"./shared/comment.ts/~/Comment.authorAvatarMime.html","deprecated":false},{"id":"namespace_createcommentrequest","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CreateCommentRequest","file":"shared/comment.ts","doc":"Passed to POST /api/dumps/:dumpId/comments by CommentThread, and by CommentNode for a reply. The body must not be blank.","url":"./shared/comment.ts/~/CreateCommentRequest.html","deprecated":false},{"id":"namespace_createcommentrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CreateCommentRequest.body","file":"shared/comment.ts","doc":"","url":"./shared/comment.ts/~/CreateCommentRequest.body.html","deprecated":false},{"id":"namespace_createcommentrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CreateCommentRequest.parentId","file":"shared/comment.ts","doc":"","url":"./shared/comment.ts/~/CreateCommentRequest.parentId.html","deprecated":false},{"id":"namespace_updatecommentrequest","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UpdateCommentRequest","file":"shared/comment.ts","doc":"Passed to PATCH /api/comments/:commentId by CommentNode.","url":"./shared/comment.ts/~/UpdateCommentRequest.html","deprecated":false},{"id":"namespace_updatecommentrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UpdateCommentRequest.body","file":"shared/comment.ts","doc":"","url":"./shared/comment.ts/~/UpdateCommentRequest.body.html","deprecated":false},{"id":"namespace_communitystats","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CommunityStats","file":"shared/community.ts","doc":"Returned by GET /api/community?period= to the Community page, and gathered by community-service.ts, which the digests read too.","url":"./shared/community.ts/~/CommunityStats.html","deprecated":false},{"id":"namespace_communitystats","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommunityStats.from","file":"shared/community.ts","doc":"The period covered, from from to to.","url":"./shared/community.ts/~/CommunityStats.from.html","deprecated":false},{"id":"namespace_communitystats","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommunityStats.to","file":"shared/community.ts","doc":"","url":"./shared/community.ts/~/CommunityStats.to.html","deprecated":false},{"id":"namespace_communitystats","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommunityStats.top","file":"shared/community.ts","doc":"The most upvoted public dumps posted in it, 10 at most.","url":"./shared/community.ts/~/CommunityStats.top.html","deprecated":false},{"id":"namespace_communitystats","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommunityStats.members","file":"shared/community.ts","doc":"In sign-up order, each with invitedByUsername when someone invited them.","url":"./shared/community.ts/~/CommunityStats.members.html","deprecated":false},{"id":"namespace_communitystats","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommunityStats.playlists","file":"shared/community.ts","doc":"The public playlists created in it, the fullest first, with dumpCount.","url":"./shared/community.ts/~/CommunityStats.playlists.html","deprecated":false},{"id":"namespace_communitystats","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommunityStats.chatMessages","file":"shared/community.ts","doc":"","url":"./shared/community.ts/~/CommunityStats.chatMessages.html","deprecated":false},{"id":"namespace_communitystats","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommunityStats.totals","file":"shared/community.ts","doc":"Public dumps posted, upvotes cast and comments written in it.","url":"./shared/community.ts/~/CommunityStats.totals.html","deprecated":false},{"id":"namespace_communitystats","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommunityStats.totals.dumps","file":"shared/community.ts","doc":"","url":"./shared/community.ts/~/CommunityStats.totals.dumps.html","deprecated":false},{"id":"namespace_communitystats","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommunityStats.totals.upvotes","file":"shared/community.ts","doc":"","url":"./shared/community.ts/~/CommunityStats.totals.upvotes.html","deprecated":false},{"id":"namespace_communitystats","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommunityStats.totals.comments","file":"shared/community.ts","doc":"","url":"./shared/community.ts/~/CommunityStats.totals.comments.html","deprecated":false},{"id":"namespace_communityitem","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CommunityItem","file":"shared/community.ts","doc":"Names a dump or a playlist in a CommunityEvent: its title, and what dumpPath or playlistPath builds its page's path from.","url":"./shared/community.ts/~/CommunityItem.html","deprecated":false},{"id":"namespace_communityitem","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommunityItem.title","file":"shared/community.ts","doc":"","url":"./shared/community.ts/~/CommunityItem.title.html","deprecated":false},{"id":"namespace_dumppostedevent","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"DumpPostedEvent","file":"shared/community.ts","doc":"A public dump was posted. A dump made public later keeps its date.","url":"./shared/community.ts/~/DumpPostedEvent.html","deprecated":false},{"id":"namespace_dumppostedevent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpPostedEvent.type","file":"shared/community.ts","doc":"","url":"./shared/community.ts/~/DumpPostedEvent.type.html","deprecated":false},{"id":"namespace_dumppostedevent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpPostedEvent.dump","file":"shared/community.ts","doc":"","url":"./shared/community.ts/~/DumpPostedEvent.dump.html","deprecated":false},{"id":"namespace_playlistcreatedevent","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PlaylistCreatedEvent","file":"shared/community.ts","doc":"A public playlist was created.","url":"./shared/community.ts/~/PlaylistCreatedEvent.html","deprecated":false},{"id":"namespace_playlistcreatedevent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistCreatedEvent.type","file":"shared/community.ts","doc":"","url":"./shared/community.ts/~/PlaylistCreatedEvent.type.html","deprecated":false},{"id":"namespace_playlistcreatedevent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistCreatedEvent.playlist","file":"shared/community.ts","doc":"","url":"./shared/community.ts/~/PlaylistCreatedEvent.playlist.html","deprecated":false},{"id":"namespace_dumpcommentedevent","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"DumpCommentedEvent","file":"shared/community.ts","doc":"A public dump got a comment. However many it got, the feed tells of its latest alone.","url":"./shared/community.ts/~/DumpCommentedEvent.html","deprecated":false},{"id":"namespace_dumpcommentedevent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpCommentedEvent.type","file":"shared/community.ts","doc":"","url":"./shared/community.ts/~/DumpCommentedEvent.type.html","deprecated":false},{"id":"namespace_dumpcommentedevent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpCommentedEvent.dump","file":"shared/community.ts","doc":"","url":"./shared/community.ts/~/DumpCommentedEvent.dump.html","deprecated":false},{"id":"namespace_dumpcommentedevent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpCommentedEvent.commentId","file":"shared/community.ts","doc":"For the #comment-<id> anchor on the dump's page.","url":"./shared/community.ts/~/DumpCommentedEvent.commentId.html","deprecated":false},{"id":"namespace_dumpupvotedevent","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"DumpUpvotedEvent","file":"shared/community.ts","doc":"A public dump got an upvote, told as DumpCommentedEvent is.","url":"./shared/community.ts/~/DumpUpvotedEvent.html","deprecated":false},{"id":"namespace_dumpupvotedevent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpUpvotedEvent.type","file":"shared/community.ts","doc":"","url":"./shared/community.ts/~/DumpUpvotedEvent.type.html","deprecated":false},{"id":"namespace_dumpupvotedevent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpUpvotedEvent.dump","file":"shared/community.ts","doc":"","url":"./shared/community.ts/~/DumpUpvotedEvent.dump.html","deprecated":false},{"id":"namespace_userjoinedevent","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UserJoinedEvent","file":"shared/community.ts","doc":"Someone joined the site: username is theirs.","url":"./shared/community.ts/~/UserJoinedEvent.html","deprecated":false},{"id":"namespace_userjoinedevent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserJoinedEvent.type","file":"shared/community.ts","doc":"","url":"./shared/community.ts/~/UserJoinedEvent.type.html","deprecated":false},{"id":"namespace_userjoinedevent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserJoinedEvent.invitedByUsername","file":"shared/community.ts","doc":"","url":"./shared/community.ts/~/UserJoinedEvent.invitedByUsername.html","deprecated":false},{"id":"namespace_communityevent","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"CommunityEvent","file":"shared/community.ts","doc":"One line of the community feed, told apart by type.","url":"./shared/community.ts/~/CommunityEvent.html","deprecated":false},{"id":"namespace_communityfeed","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CommunityFeed","file":"shared/community.ts","doc":"Returned by GET /api/community/feed to CommunityFeedProvider, which asks again as the socket tells of changes, and rendered by the CommunityFeed component with who is online, which the client knows from its socket. community-service.ts gathers it. Everything in it is public: every reader gets the same feed.","url":"./shared/community.ts/~/CommunityFeed.html","deprecated":false},{"id":"namespace_communityfeed","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommunityFeed.events","file":"shared/community.ts","doc":"The latest events, newest first, 12 at most.","url":"./shared/community.ts/~/CommunityFeed.events.html","deprecated":false},{"id":"namespace_communityfeed","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommunityFeed.week","file":"shared/community.ts","doc":"The last week's figures, as /community shows them: as of the server's last refresh.","url":"./shared/community.ts/~/CommunityFeed.week.html","deprecated":false},{"id":"namespace_communityeventbase","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CommunityEventBase","file":"shared/community.ts","doc":"What every CommunityEvent carries.","url":"./shared/community.ts/~/CommunityEventBase.html","deprecated":false},{"id":"namespace_communityeventbase","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommunityEventBase.id","file":"shared/community.ts","doc":"The event's kind and what it is about, dump_upvoted:<dump id>: unique in a feed, where a dump has one event of each kind at most.","url":"./shared/community.ts/~/CommunityEventBase.id.html","deprecated":false},{"id":"namespace_communityeventbase","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommunityEventBase.at","file":"shared/community.ts","doc":"","url":"./shared/community.ts/~/CommunityEventBase.at.html","deprecated":false},{"id":"namespace_communityeventbase","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommunityEventBase.username","file":"shared/community.ts","doc":"Who did it, by their current name.","url":"./shared/community.ts/~/CommunityEventBase.username.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"DIGEST_MESSAGES","file":"shared/digest-messages.ts","doc":"The shared messages, by name.","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.weekly","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.weekly.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.weekly.id","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.weekly.id.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.weekly.message","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.weekly.message.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.monthly","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.monthly.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.monthly.id","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.monthly.id.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.monthly.message","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.monthly.message.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.weeklyOff","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.weeklyOff.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.weeklyOff.id","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.weeklyOff.id.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.weeklyOff.message","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.weeklyOff.message.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.monthlyOff","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.monthlyOff.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.monthlyOff.id","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.monthlyOff.id.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.monthlyOff.message","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.monthlyOff.message.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.community","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.community.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.community.id","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.community.id.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.community.message","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.community.message.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.topWeek","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.topWeek.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.topWeek.id","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.topWeek.id.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.topWeek.message","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.topWeek.message.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.topMonth","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.topMonth.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.topMonth.id","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.topMonth.id.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.topMonth.message","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.topMonth.message.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.newMembers","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.newMembers.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.newMembers.id","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.newMembers.id.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.newMembers.message","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.newMembers.message.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.newPlaylists","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.newPlaylists.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.newPlaylists.id","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.newPlaylists.id.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.newPlaylists.message","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.newPlaylists.message.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.invitedBy","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.invitedBy.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.invitedBy.id","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.invitedBy.id.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.invitedBy.message","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.invitedBy.message.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.invitedByYou","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.invitedByYou.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.invitedByYou.id","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.invitedByYou.id.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.invitedByYou.message","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.invitedByYou.message.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.statDumps","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.statDumps.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.statDumps.id","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.statDumps.id.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.statDumps.message","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.statDumps.message.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.statChat","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.statChat.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.statChat.id","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.statChat.id.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.statChat.message","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.statChat.message.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.countUpvotes","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.countUpvotes.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.countUpvotes.id","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.countUpvotes.id.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.countUpvotes.message","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.countUpvotes.message.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.countComments","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.countComments.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.countComments.id","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.countComments.id.html","deprecated":false},{"id":"namespace_digest_messages","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DIGEST_MESSAGES.countComments.message","file":"shared/digest-messages.ts","doc":"","url":"./shared/digest-messages.ts/~/DIGEST_MESSAGES.countComments.message.html","deprecated":false},{"id":"namespace_richcontenttype","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"RichContentType","file":"shared/dump.ts","doc":"Names the kind of link a RichContent previews: a site the player plays its own way, or generic for any other page, this site's included.","url":"./shared/dump.ts/~/RichContentType.html","deprecated":false},{"id":"namespace_richcontent","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"RichContent","file":"shared/dump.ts","doc":"Built by a provider of rich-content-service.ts when a link is posted or previewed, and stored with the dump as JSON. The frontend's RichContentCard and player read it.","url":"./shared/dump.ts/~/RichContent.html","deprecated":false},{"id":"namespace_richcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RichContent.type","file":"shared/dump.ts","doc":"The player picks how to play the link by it.","url":"./shared/dump.ts/~/RichContent.type.html","deprecated":false},{"id":"namespace_richcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RichContent.url","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/RichContent.url.html","deprecated":false},{"id":"namespace_richcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RichContent.siteName","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/RichContent.siteName.html","deprecated":false},{"id":"namespace_richcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RichContent.title","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/RichContent.title.html","deprecated":false},{"id":"namespace_richcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RichContent.description","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/RichContent.description.html","deprecated":false},{"id":"namespace_richcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RichContent.thumbnailUrl","file":"shared/dump.ts","doc":"A real preview image (og:image, a large content image, a video still). Never a favicon — an absent value means \"this page offers no artwork\", which is what makes the generated placeholder possible.","url":"./shared/dump.ts/~/RichContent.thumbnailUrl.html","deprecated":false},{"id":"namespace_richcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RichContent.faviconUrl","file":"shared/dump.ts","doc":"Used as the placeholder's glyph.","url":"./shared/dump.ts/~/RichContent.faviconUrl.html","deprecated":false},{"id":"namespace_richcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RichContent.accentColor","file":"shared/dump.ts","doc":"The page's declared brand color, normalized to #rrggbb.","url":"./shared/dump.ts/~/RichContent.accentColor.html","deprecated":false},{"id":"namespace_richcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RichContent.embedUrl","file":"shared/dump.ts","doc":"The player a YouTube, Bandcamp or SoundCloud link plays in, framed by the frontend.","url":"./shared/dump.ts/~/RichContent.embedUrl.html","deprecated":false},{"id":"namespace_dump","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"Dump","file":"shared/dump.ts","doc":"Returned by every endpoint that answers dumps, and pushed to clients by the dump_created and dump_updated socket messages. A URL dump has url and richContent, a file dump the file… fields. A private dump reaches its poster only.","url":"./shared/dump.ts/~/Dump.html","deprecated":false},{"id":"namespace_dump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Dump.id","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/Dump.id.html","deprecated":false},{"id":"namespace_dump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Dump.kind","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/Dump.kind.html","deprecated":false},{"id":"namespace_dump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Dump.title","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/Dump.title.html","deprecated":false},{"id":"namespace_dump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Dump.slug","file":"shared/dump.ts","doc":"Names the dump in its page's path, dumpPath (shared/paths.ts) building it with ownerUsername. Made from the title on creation, it changes only when edited, and is unique among its poster's dumps.","url":"./shared/dump.ts/~/Dump.slug.html","deprecated":false},{"id":"namespace_dump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Dump.comment","file":"shared/dump.ts","doc":"The poster's note on the dump, in Markdown.","url":"./shared/dump.ts/~/Dump.comment.html","deprecated":false},{"id":"namespace_dump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Dump.userId","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/Dump.userId.html","deprecated":false},{"id":"namespace_dump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Dump.ownerUsername","file":"shared/dump.ts","doc":"The poster's current name, which the dump's path starts with.","url":"./shared/dump.ts/~/Dump.ownerUsername.html","deprecated":false},{"id":"namespace_dump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Dump.createdAt","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/Dump.createdAt.html","deprecated":false},{"id":"namespace_dump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Dump.updatedAt","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/Dump.updatedAt.html","deprecated":false},{"id":"namespace_dump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Dump.url","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/Dump.url.html","deprecated":false},{"id":"namespace_dump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Dump.richContent","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/Dump.richContent.html","deprecated":false},{"id":"namespace_dump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Dump.fileName","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/Dump.fileName.html","deprecated":false},{"id":"namespace_dump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Dump.fileMime","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/Dump.fileMime.html","deprecated":false},{"id":"namespace_dump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Dump.fileSize","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/Dump.fileSize.html","deprecated":false},{"id":"namespace_dump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Dump.voteCount","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/Dump.voteCount.html","deprecated":false},{"id":"namespace_dump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Dump.commentCount","file":"shared/dump.ts","doc":"Deleted comments are not counted.","url":"./shared/dump.ts/~/Dump.commentCount.html","deprecated":false},{"id":"namespace_dump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Dump.isPrivate","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/Dump.isPrivate.html","deprecated":false},{"id":"namespace_dump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Dump.thumbnailMime","file":"shared/dump.ts","doc":"Set when the poster uploaded a custom thumbnail.","url":"./shared/dump.ts/~/Dump.thumbnailMime.html","deprecated":false},{"id":"namespace_dump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Dump.categoryIds","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/Dump.categoryIds.html","deprecated":false},{"id":"namespace_dumpurlmatch","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"DumpUrlMatch","file":"shared/dump.ts","doc":"Returned by GET /api/dumps?url= for each dump already posted with the link being typed, and shown by the create form's DuplicateNotice. It holds only what the notice displays and links to.","url":"./shared/dump.ts/~/DumpUrlMatch.html","deprecated":false},{"id":"namespace_dumpurlmatch","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpUrlMatch.id","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/DumpUrlMatch.id.html","deprecated":false},{"id":"namespace_dumpurlmatch","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpUrlMatch.slug","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/DumpUrlMatch.slug.html","deprecated":false},{"id":"namespace_dumpurlmatch","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpUrlMatch.title","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/DumpUrlMatch.title.html","deprecated":false},{"id":"namespace_dumpurlmatch","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpUrlMatch.ownerUsername","file":"shared/dump.ts","doc":"The poster's username.","url":"./shared/dump.ts/~/DumpUrlMatch.ownerUsername.html","deprecated":false},{"id":"namespace_dumpurlmatch","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpUrlMatch.createdAt","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/DumpUrlMatch.createdAt.html","deprecated":false},{"id":"namespace_dumpurlmatch","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpUrlMatch.voteCount","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/DumpUrlMatch.voteCount.html","deprecated":false},{"id":"namespace_dumpurlmatch","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpUrlMatch.commentCount","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/DumpUrlMatch.commentCount.html","deprecated":false},{"id":"namespace_linkpreview","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"LinkPreview","file":"shared/dump.ts","doc":"Returned by GET /api/remote/preview to the create form, which shows it before the link is posted.","url":"./shared/dump.ts/~/LinkPreview.html","deprecated":false},{"id":"namespace_linkpreview","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"LinkPreview.reached","file":"shared/dump.ts","doc":"False when the page couldn't be fetched. richContent is then a stub holding the host name, and this flag is how the form tells a dead link from a page with no preview.","url":"./shared/dump.ts/~/LinkPreview.reached.html","deprecated":false},{"id":"namespace_linkpreview","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"LinkPreview.richContent","file":"shared/dump.ts","doc":"Null only for a link that doesn't parse, which the route rejects before fetching anyway.","url":"./shared/dump.ts/~/LinkPreview.richContent.html","deprecated":false},{"id":"namespace_createurldumprequest","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CreateUrlDumpRequest","file":"shared/dump.ts","doc":"Passed by the create form to POST /api/dumps as a JSON body, to post a link. A file is posted as a multipart form instead.","url":"./shared/dump.ts/~/CreateUrlDumpRequest.html","deprecated":false},{"id":"namespace_createurldumprequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CreateUrlDumpRequest.url","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/CreateUrlDumpRequest.url.html","deprecated":false},{"id":"namespace_createurldumprequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CreateUrlDumpRequest.title","file":"shared/dump.ts","doc":"Replaces the title read from the page, when the poster edited it.","url":"./shared/dump.ts/~/CreateUrlDumpRequest.title.html","deprecated":false},{"id":"namespace_createurldumprequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CreateUrlDumpRequest.comment","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/CreateUrlDumpRequest.comment.html","deprecated":false},{"id":"namespace_createurldumprequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CreateUrlDumpRequest.isPrivate","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/CreateUrlDumpRequest.isPrivate.html","deprecated":false},{"id":"namespace_createurldumprequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CreateUrlDumpRequest.categoryIds","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/CreateUrlDumpRequest.categoryIds.html","deprecated":false},{"id":"namespace_updatedumprequest","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UpdateDumpRequest","file":"shared/dump.ts","doc":"Passed to PUT /api/dumps/:dumpId by the edit page, and by the dump page's inline title edit. A field left out stays as it is.","url":"./shared/dump.ts/~/UpdateDumpRequest.html","deprecated":false},{"id":"namespace_updatedumprequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UpdateDumpRequest.url","file":"shared/dump.ts","doc":"Ignored for a file dump. A changed link has its preview fetched again.","url":"./shared/dump.ts/~/UpdateDumpRequest.url.html","deprecated":false},{"id":"namespace_updatedumprequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UpdateDumpRequest.title","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/UpdateDumpRequest.title.html","deprecated":false},{"id":"namespace_updatedumprequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UpdateDumpRequest.slug","file":"shared/dump.ts","doc":"A new slug, which the edit page's slug field sends. A title change never changes the slug by itself.","url":"./shared/dump.ts/~/UpdateDumpRequest.slug.html","deprecated":false},{"id":"namespace_updatedumprequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UpdateDumpRequest.comment","file":"shared/dump.ts","doc":"null removes the note.","url":"./shared/dump.ts/~/UpdateDumpRequest.comment.html","deprecated":false},{"id":"namespace_updatedumprequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UpdateDumpRequest.isPrivate","file":"shared/dump.ts","doc":"","url":"./shared/dump.ts/~/UpdateDumpRequest.isPrivate.html","deprecated":false},{"id":"namespace_updatedumprequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UpdateDumpRequest.categoryIds","file":"shared/dump.ts","doc":"Replaces the current categories.","url":"./shared/dump.ts/~/UpdateDumpRequest.categoryIds.html","deprecated":false},{"id":"namespace_dumpfileversion","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"dumpFileVersion","file":"shared/dump.ts","doc":"Returns a file dump's version, which the file and thumbnail URLs carry as ?v=: the frontend's dumpFileUrl and dumpThumbnailUrl, and the digest's thumbnails. It changes whenever the file may have, so the file and thumbnail routes cache a URL naming the current one for good and revalidate any other. Without its dates, a dump gets a version no route serves as current.","url":"./shared/dump.ts/~/dumpFileVersion.html","deprecated":false},{"id":"namespace_federation_version","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"FEDERATION_VERSION","file":"shared/federation.ts","doc":"The version of the protocol below, which an instance announces in its InstanceMetadata. An instance refuses one announcing another.","url":"./shared/federation.ts/~/FEDERATION_VERSION.html","deprecated":false},{"id":"namespace_instancemetadata","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"InstanceMetadata","file":"shared/federation.ts","doc":"Served by every instance at /.well-known/openid-configuration (routes/well-known.ts), and read by another before it trusts it, starts a sign-in on it or sends it an event. The names are OpenID Connect's, and the gerbeur_ fields are this protocol's own.","url":"./shared/federation.ts/~/InstanceMetadata.html","deprecated":false},{"id":"namespace_instancemetadata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InstanceMetadata.issuer","file":"shared/federation.ts","doc":"The instance's public URL, an origin, which names it in every token.","url":"./shared/federation.ts/~/InstanceMetadata.issuer.html","deprecated":false},{"id":"namespace_instancemetadata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InstanceMetadata.authorization_endpoint","file":"shared/federation.ts","doc":"Its /authorize page, where a user lets another instance sign them in.","url":"./shared/federation.ts/~/InstanceMetadata.authorization_endpoint.html","deprecated":false},{"id":"namespace_instancemetadata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InstanceMetadata.token_endpoint","file":"shared/federation.ts","doc":"POST /api/oauth/tokens, which trades a code for an identity token.","url":"./shared/federation.ts/~/InstanceMetadata.token_endpoint.html","deprecated":false},{"id":"namespace_instancemetadata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InstanceMetadata.jwks_uri","file":"shared/federation.ts","doc":"GET /.well-known/jwks.json, its public keys.","url":"./shared/federation.ts/~/InstanceMetadata.jwks_uri.html","deprecated":false},{"id":"namespace_instancemetadata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InstanceMetadata.response_types_supported","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/InstanceMetadata.response_types_supported.html","deprecated":false},{"id":"namespace_instancemetadata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InstanceMetadata.grant_types_supported","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/InstanceMetadata.grant_types_supported.html","deprecated":false},{"id":"namespace_instancemetadata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InstanceMetadata.subject_types_supported","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/InstanceMetadata.subject_types_supported.html","deprecated":false},{"id":"namespace_instancemetadata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InstanceMetadata.id_token_signing_alg_values_supported","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/InstanceMetadata.id_token_signing_alg_values_supported.html","deprecated":false},{"id":"namespace_instancemetadata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InstanceMetadata.code_challenge_methods_supported","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/InstanceMetadata.code_challenge_methods_supported.html","deprecated":false},{"id":"namespace_instancemetadata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InstanceMetadata.scopes_supported","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/InstanceMetadata.scopes_supported.html","deprecated":false},{"id":"namespace_instancemetadata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InstanceMetadata.gerbeur_federation","file":"shared/federation.ts","doc":"FEDERATION_VERSION.","url":"./shared/federation.ts/~/InstanceMetadata.gerbeur_federation.html","deprecated":false},{"id":"namespace_instancemetadata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InstanceMetadata.gerbeur_site_name","file":"shared/federation.ts","doc":"The site's name, which a consent page and the peer list show.","url":"./shared/federation.ts/~/InstanceMetadata.gerbeur_site_name.html","deprecated":false},{"id":"namespace_instancemetadata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InstanceMetadata.gerbeur_redirect_uri","file":"shared/federation.ts","doc":"Where its home instance sends a user back once they consent, as a client: its /federation/callback page, on its frontend.","url":"./shared/federation.ts/~/InstanceMetadata.gerbeur_redirect_uri.html","deprecated":false},{"id":"namespace_instancemetadata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InstanceMetadata.gerbeur_events_endpoint","file":"shared/federation.ts","doc":"POST /api/federation/events, where it receives a home's events.","url":"./shared/federation.ts/~/InstanceMetadata.gerbeur_events_endpoint.html","deprecated":false},{"id":"namespace_instancemetadata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InstanceMetadata.gerbeur_outgoing","file":"shared/federation.ts","doc":"Whether its users may sign in to other instances, so that a client refuses at once to send them to its /authorize page, which would. An instance that doesn't say lets them.","url":"./shared/federation.ts/~/InstanceMetadata.gerbeur_outgoing.html","deprecated":false},{"id":"namespace_isinstancemetadata","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isInstanceMetadata","file":"shared/federation.ts","doc":"Checks whether value is an InstanceMetadata of this protocol's version, as remote/gerbeur-instance.ts must before reading one.","url":"./shared/federation.ts/~/isInstanceMetadata.html","deprecated":false},{"id":"namespace_parseinstance","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"parseInstance","file":"shared/federation.ts","doc":"Returns the origin of the instance input names, or null when it names none. Someone may type a bare host (music.example, taken as https), a URL, or a handle's host with its port (localhost:8001); a URL with a path names no instance. Whether plain http is allowed is the server's call.","url":"./shared/federation.ts/~/parseInstance.html","deprecated":false},{"id":"namespace_instancehost","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"instanceHost","file":"shared/federation.ts","doc":"Returns the host of the instance at issuer, with its port if it has one: the part after the @ of its users' handles here (alice@music.example).","url":"./shared/federation.ts/~/instanceHost.html","deprecated":false},{"id":"namespace_peerstatus","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"PeerStatus","file":"shared/federation.ts","doc":"What an admin decided about an instance. Users of a trusted one sign in here directly; those of a blocked one never do, and its users already here are signed out. An instance with neither is invite only: its users sign in here with an invite.","url":"./shared/federation.ts/~/PeerStatus.html","deprecated":false},{"id":"namespace_peer_statuses","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"PEER_STATUSES","file":"shared/federation.ts","doc":"Every PeerStatus.","url":"./shared/federation.ts/~/PEER_STATUSES.html","deprecated":false},{"id":"namespace_ispeerstatus","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isPeerStatus","file":"shared/federation.ts","doc":"Checks whether value is a PeerStatus.","url":"./shared/federation.ts/~/isPeerStatus.html","deprecated":false},{"id":"namespace_federationpeer","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"FederationPeer","file":"shared/federation.ts","doc":"Returned by GET /api/federation/peers: the login page offers each trusted one, and /manage lists them all.","url":"./shared/federation.ts/~/FederationPeer.html","deprecated":false},{"id":"namespace_federationpeer","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FederationPeer.issuer","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/FederationPeer.issuer.html","deprecated":false},{"id":"namespace_federationpeer","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FederationPeer.host","file":"shared/federation.ts","doc":"instanceHost of the issuer.","url":"./shared/federation.ts/~/FederationPeer.host.html","deprecated":false},{"id":"namespace_federationpeer","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FederationPeer.name","file":"shared/federation.ts","doc":"The site's name, as its metadata gave it when it was added.","url":"./shared/federation.ts/~/FederationPeer.name.html","deprecated":false},{"id":"namespace_federationpeer","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FederationPeer.status","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/FederationPeer.status.html","deprecated":false},{"id":"namespace_federationpeer","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FederationPeer.createdAt","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/FederationPeer.createdAt.html","deprecated":false},{"id":"namespace_setpeerrequest","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"SetPeerRequest","file":"shared/federation.ts","doc":"Sent to PUT /api/federation/peers by /manage.","url":"./shared/federation.ts/~/SetPeerRequest.html","deprecated":false},{"id":"namespace_setpeerrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SetPeerRequest.instance","file":"shared/federation.ts","doc":"As someone typed it, read with parseInstance.","url":"./shared/federation.ts/~/SetPeerRequest.instance.html","deprecated":false},{"id":"namespace_setpeerrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SetPeerRequest.status","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/SetPeerRequest.status.html","deprecated":false},{"id":"namespace_federationloginrequest","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"FederationLoginRequest","file":"shared/federation.ts","doc":"Sent to POST /api/federation/logins by the login page, or by the register page with the invite it was opened with.","url":"./shared/federation.ts/~/FederationLoginRequest.html","deprecated":false},{"id":"namespace_federationloginrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FederationLoginRequest.instance","file":"shared/federation.ts","doc":"The user's home instance, read with parseInstance.","url":"./shared/federation.ts/~/FederationLoginRequest.instance.html","deprecated":false},{"id":"namespace_federationloginrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FederationLoginRequest.inviteToken","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/FederationLoginRequest.inviteToken.html","deprecated":false},{"id":"namespace_federationloginresponse","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"FederationLoginResponse","file":"shared/federation.ts","doc":"Returned by POST /api/federation/logins: the home instance's /authorize page with the request in its query, which the client navigates to.","url":"./shared/federation.ts/~/FederationLoginResponse.html","deprecated":false},{"id":"namespace_federationloginresponse","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FederationLoginResponse.authorizeUrl","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/FederationLoginResponse.authorizeUrl.html","deprecated":false},{"id":"namespace_federationsessionrequest","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"FederationSessionRequest","file":"shared/federation.ts","doc":"Sent to POST /api/federation/sessions by the /federation/callback page, from the query the home instance sent the user back with. The answer is an AuthResponse, as a sign-in's.","url":"./shared/federation.ts/~/FederationSessionRequest.html","deprecated":false},{"id":"namespace_federationsessionrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FederationSessionRequest.code","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/FederationSessionRequest.code.html","deprecated":false},{"id":"namespace_federationsessionrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FederationSessionRequest.state","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/FederationSessionRequest.state.html","deprecated":false},{"id":"namespace_oauthclient","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"OAuthClient","file":"shared/federation.ts","doc":"Returned by GET /api/oauth/clients?client_id= to the /authorize page, which asks the user whether to sign in there.","url":"./shared/federation.ts/~/OAuthClient.html","deprecated":false},{"id":"namespace_oauthclient","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"OAuthClient.clientId","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/OAuthClient.clientId.html","deprecated":false},{"id":"namespace_oauthclient","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"OAuthClient.host","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/OAuthClient.host.html","deprecated":false},{"id":"namespace_oauthclient","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"OAuthClient.name","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/OAuthClient.name.html","deprecated":false},{"id":"namespace_oauthclient","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"OAuthClient.granted","file":"shared/federation.ts","doc":"Whether the user already let it sign them in, in which case the page doesn't ask again.","url":"./shared/federation.ts/~/OAuthClient.granted.html","deprecated":false},{"id":"namespace_authorizerequest","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"AuthorizeRequest","file":"shared/federation.ts","doc":"Sent to POST /api/oauth/codes by the /authorize page once the user consents, from the query the client instance sent them with.","url":"./shared/federation.ts/~/AuthorizeRequest.html","deprecated":false},{"id":"namespace_authorizerequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AuthorizeRequest.clientId","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/AuthorizeRequest.clientId.html","deprecated":false},{"id":"namespace_authorizerequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AuthorizeRequest.redirectUri","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/AuthorizeRequest.redirectUri.html","deprecated":false},{"id":"namespace_authorizerequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AuthorizeRequest.state","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/AuthorizeRequest.state.html","deprecated":false},{"id":"namespace_authorizerequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AuthorizeRequest.codeChallenge","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/AuthorizeRequest.codeChallenge.html","deprecated":false},{"id":"namespace_authorizerequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AuthorizeRequest.codeChallengeMethod","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/AuthorizeRequest.codeChallengeMethod.html","deprecated":false},{"id":"namespace_authorizerequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AuthorizeRequest.nonce","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/AuthorizeRequest.nonce.html","deprecated":false},{"id":"namespace_authorizeresponse","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"AuthorizeResponse","file":"shared/federation.ts","doc":"Returned by POST /api/oauth/codes: the client's callback page with the code, where the /authorize page sends the user.","url":"./shared/federation.ts/~/AuthorizeResponse.html","deprecated":false},{"id":"namespace_authorizeresponse","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AuthorizeResponse.redirectTo","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/AuthorizeResponse.redirectTo.html","deprecated":false},{"id":"namespace_federationgrant","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"FederationGrant","file":"shared/federation.ts","doc":"Returned by GET /api/me/grants to the settings page: an instance the user let their account sign in to.","url":"./shared/federation.ts/~/FederationGrant.html","deprecated":false},{"id":"namespace_federationgrant","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FederationGrant.clientId","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/FederationGrant.clientId.html","deprecated":false},{"id":"namespace_federationgrant","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FederationGrant.host","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/FederationGrant.host.html","deprecated":false},{"id":"namespace_federationgrant","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FederationGrant.name","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/FederationGrant.name.html","deprecated":false},{"id":"namespace_federationgrant","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FederationGrant.grantedAt","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/FederationGrant.grantedAt.html","deprecated":false},{"id":"namespace_federationgrant","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FederationGrant.lastUsedAt","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/FederationGrant.lastUsedAt.html","deprecated":false},{"id":"namespace_identityclaims","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"IdentityClaims","file":"shared/federation.ts","doc":"Carried by an identity token and by an update event: what a home instance tells another of a user. The names are OpenID Connect's.","url":"./shared/federation.ts/~/IdentityClaims.html","deprecated":false},{"id":"namespace_identityclaims","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"IdentityClaims.preferred_username","file":"shared/federation.ts","doc":"The user's name at home; the client calls them <name>@<host>.","url":"./shared/federation.ts/~/IdentityClaims.preferred_username.html","deprecated":false},{"id":"namespace_identityclaims","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"IdentityClaims.email","file":"shared/federation.ts","doc":"","url":"./shared/federation.ts/~/IdentityClaims.email.html","deprecated":false},{"id":"namespace_identityclaims","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"IdentityClaims.picture","file":"shared/federation.ts","doc":"Their avatar's URL at home, versioned; absent without one.","url":"./shared/federation.ts/~/IdentityClaims.picture.html","deprecated":false},{"id":"namespace_federationevent","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"FederationEvent","file":"shared/federation.ts","doc":"The payload of a signed event, which a home instance sends each instance a user signed in to (POST /api/federation/events): update when their name, email or avatar changed, revoke when their sessions there must end, after a password change or when they withdraw the grant.","url":"./shared/federation.ts/~/FederationEvent.html","deprecated":false},{"id":"namespace_isfederationevent","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isFederationEvent","file":"shared/federation.ts","doc":"Checks whether value is a FederationEvent, as the events endpoint must once the signature is verified.","url":"./shared/federation.ts/~/isFederationEvent.html","deprecated":false},{"id":"namespace_isidentityclaims","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isIdentityClaims","file":"shared/federation.ts","doc":"Checks whether value carries the IdentityClaims, as a client must before creating or updating an account from them.","url":"./shared/federation.ts/~/isIdentityClaims.html","deprecated":false},{"id":"namespace_followstatus","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"FollowStatus","file":"shared/follow.ts","doc":"Returned by GET /api/me/follow to FollowProvider, which then keeps it up to date itself as the user follows and unfollows.","url":"./shared/follow.ts/~/FollowStatus.html","deprecated":false},{"id":"namespace_followstatus","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FollowStatus.followedUserIds","file":"shared/follow.ts","doc":"","url":"./shared/follow.ts/~/FollowStatus.followedUserIds.html","deprecated":false},{"id":"namespace_followstatus","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FollowStatus.followedPlaylistIds","file":"shared/follow.ts","doc":"","url":"./shared/follow.ts/~/FollowStatus.followedPlaylistIds.html","deprecated":false},{"id":"namespace_image_widths","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"IMAGE_WIDTHS","file":"shared/image.ts","doc":"The widths, in pixels, smallest first: an avatar on a dense screen, a small cover, a card on a phone, and the widest feed card on a dense screen.","url":"./shared/image.ts/~/IMAGE_WIDTHS.html","deprecated":false},{"id":"namespace_imagewidth","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"ImageWidth","file":"shared/image.ts","doc":"One of IMAGE_WIDTHS.","url":"./shared/image.ts/~/ImageWidth.html","deprecated":false},{"id":"namespace_max_image_width","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"MAX_IMAGE_WIDTH","file":"shared/image.ts","doc":"The largest of IMAGE_WIDTHS, which a thumbnail never exceeds.","url":"./shared/image.ts/~/MAX_IMAGE_WIDTH.html","deprecated":false},{"id":"namespace_snapimagewidth","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"snapImageWidth","file":"shared/image.ts","doc":"Returns the narrowest of IMAGE_WIDTHS that covers width pixels, or the widest when none does.","url":"./shared/image.ts/~/snapImageWidth.html","deprecated":false},{"id":"namespace_parseimagewidth","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"parseImageWidth","file":"shared/image.ts","doc":"Returns the width a ?w= value asks for, snapped to IMAGE_WIDTHS, or null when it is absent or not a positive number, which asks for the image as it is.","url":"./shared/image.ts/~/parseImageWidth.html","deprecated":false},{"id":"namespace_locales","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"LOCALES","file":"shared/locale.ts","doc":"Lists the locales the app is translated into.","url":"./shared/locale.ts/~/LOCALES.html","deprecated":false},{"id":"namespace_locale","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"Locale","file":"shared/locale.ts","doc":"One of the LOCALES.","url":"./shared/locale.ts/~/Locale.html","deprecated":false},{"id":"namespace_source_locale","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"SOURCE_LOCALE","file":"shared/locale.ts","doc":"The locale the messages are written in, and the fallback for any other.","url":"./shared/locale.ts/~/SOURCE_LOCALE.html","deprecated":false},{"id":"namespace_islocale","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isLocale","file":"shared/locale.ts","doc":"Checks whether value is a Locale.","url":"./shared/locale.ts/~/isLocale.html","deprecated":false},{"id":"namespace_markdowntoplaintext","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"markdownToPlainText","file":"shared/markdown.ts","doc":"Returns the Markdown md as one line of plain text. Images become their alt text, or imageLabel without one, and links their text. It also takes a body cut short, possibly inside a link, as the server cuts a chat message's replyToBody: the unfinished link then shows as its text, without half a URL.","url":"./shared/markdown.ts/~/markdownToPlainText.html","deprecated":false},{"id":"namespace_mention_re","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"MENTION_RE","file":"shared/mention.ts","doc":"Matches an @handle, a local @name or a remote user's @name@host (HANDLE_SOURCE), with the handle as its first group. The @ must not follow a word character, so an email address mentions no one. Nor may it follow [ or (, which leaves out a Markdown link's text or URL starting with @, and also a plain (@name). The editor's suggestions match its source at the caret; the rest goes through mentionedUsernames. Markdown links mentions with a looser pattern of its own, on text already parsed, where code and URLs are out of the way.","url":"./shared/mention.ts/~/MENTION_RE.html","deprecated":false},{"id":"namespace_mentionedusernames","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"mentionedUsernames","file":"shared/mention.ts","doc":"Returns the names body mentions, in lower case, each once. Code, fenced or inline, and URLs mention no one, as Markdown shows them. The server notifies by it, and the chat highlights and chimes by it.","url":"./shared/mention.ts/~/mentionedUsernames.html","deprecated":false},{"id":"namespace_everyone","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"EVERYONE","file":"shared/mention.ts","doc":"The name @everyone reaches. Said by a role with chat:everyone in the chat, it notifies every user, so no account may take it (assertUsernameAvailable).","url":"./shared/mention.ts/~/EVERYONE.html","deprecated":false},{"id":"namespace_mentionseveryone","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"mentionsEveryone","file":"shared/mention.ts","doc":"Checks whether body says @everyone, in any case, by the rule of mentionedUsernames. Only the chat service reads it, to set a message's mentionsEveryone when its author may; the client reads that flag, not the text.","url":"./shared/mention.ts/~/mentionsEveryone.html","deprecated":false},{"id":"namespace_notificationtype","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"NotificationType","file":"shared/notification.ts","doc":"Says which of the …Data interfaces a notification's data is. Each value has one notify… trigger in notification-service.ts.","url":"./shared/notification.ts/~/NotificationType.html","deprecated":false},{"id":"namespace_dumpref","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"DumpRef","file":"shared/notification.ts","doc":"Where a notification's dump is now, for its link (dumpPath). The server joins it each time it sends the notification, so a renamed dump or poster still links right; it is absent once the dump is deleted.","url":"./shared/notification.ts/~/DumpRef.html","deprecated":false},{"id":"namespace_dumpref","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpRef.dumpSlug","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/DumpRef.dumpSlug.html","deprecated":false},{"id":"namespace_dumpref","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpRef.dumpOwnerUsername","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/DumpRef.dumpOwnerUsername.html","deprecated":false},{"id":"namespace_playlistref","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PlaylistRef","file":"shared/notification.ts","doc":"Where a notification's playlist is now, joined as DumpRef is.","url":"./shared/notification.ts/~/PlaylistRef.html","deprecated":false},{"id":"namespace_playlistref","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistRef.playlistSlug","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/PlaylistRef.playlistSlug.html","deprecated":false},{"id":"namespace_playlistref","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistRef.playlistOwnerUsername","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/PlaylistRef.playlistOwnerUsername.html","deprecated":false},{"id":"namespace_playlistfolloweddata","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PlaylistFollowedData","file":"shared/notification.ts","doc":"Carried by a playlist_followed notification, sent to a playlist's owner.","url":"./shared/notification.ts/~/PlaylistFollowedData.html","deprecated":false},{"id":"namespace_playlistfolloweddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistFollowedData.followerId","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/PlaylistFollowedData.followerId.html","deprecated":false},{"id":"namespace_playlistfolloweddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistFollowedData.followerUsername","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/PlaylistFollowedData.followerUsername.html","deprecated":false},{"id":"namespace_playlistfolloweddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistFollowedData.playlistId","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/PlaylistFollowedData.playlistId.html","deprecated":false},{"id":"namespace_playlistfolloweddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistFollowedData.playlistTitle","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/PlaylistFollowedData.playlistTitle.html","deprecated":false},{"id":"namespace_userfolloweddata","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UserFollowedData","file":"shared/notification.ts","doc":"Carried by a user_followed notification, sent to the user followed.","url":"./shared/notification.ts/~/UserFollowedData.html","deprecated":false},{"id":"namespace_userfolloweddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserFollowedData.followerId","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/UserFollowedData.followerId.html","deprecated":false},{"id":"namespace_userfolloweddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserFollowedData.followerUsername","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/UserFollowedData.followerUsername.html","deprecated":false},{"id":"namespace_userdumpposteddata","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UserDumpPostedData","file":"shared/notification.ts","doc":"Carried by a user_dump_posted notification, sent to the followers of a user who posted a public dump.","url":"./shared/notification.ts/~/UserDumpPostedData.html","deprecated":false},{"id":"namespace_userdumpposteddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserDumpPostedData.dumperId","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/UserDumpPostedData.dumperId.html","deprecated":false},{"id":"namespace_userdumpposteddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserDumpPostedData.dumperUsername","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/UserDumpPostedData.dumperUsername.html","deprecated":false},{"id":"namespace_userdumpposteddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserDumpPostedData.dumpId","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/UserDumpPostedData.dumpId.html","deprecated":false},{"id":"namespace_userdumpposteddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserDumpPostedData.dumpTitle","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/UserDumpPostedData.dumpTitle.html","deprecated":false},{"id":"namespace_playlistdumpaddeddata","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PlaylistDumpAddedData","file":"shared/notification.ts","doc":"Carried by a playlist_dump_added notification, sent to the followers of a public playlist when a public dump is added to it.","url":"./shared/notification.ts/~/PlaylistDumpAddedData.html","deprecated":false},{"id":"namespace_playlistdumpaddeddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistDumpAddedData.dumpId","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/PlaylistDumpAddedData.dumpId.html","deprecated":false},{"id":"namespace_playlistdumpaddeddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistDumpAddedData.dumpTitle","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/PlaylistDumpAddedData.dumpTitle.html","deprecated":false},{"id":"namespace_playlistdumpaddeddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistDumpAddedData.playlistId","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/PlaylistDumpAddedData.playlistId.html","deprecated":false},{"id":"namespace_playlistdumpaddeddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistDumpAddedData.playlistTitle","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/PlaylistDumpAddedData.playlistTitle.html","deprecated":false},{"id":"namespace_dumpupvoteddata","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"DumpUpvotedData","file":"shared/notification.ts","doc":"Carried by a dump_upvoted notification, sent to the dump's poster.","url":"./shared/notification.ts/~/DumpUpvotedData.html","deprecated":false},{"id":"namespace_dumpupvoteddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpUpvotedData.voterId","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/DumpUpvotedData.voterId.html","deprecated":false},{"id":"namespace_dumpupvoteddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpUpvotedData.voterUsername","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/DumpUpvotedData.voterUsername.html","deprecated":false},{"id":"namespace_dumpupvoteddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpUpvotedData.dumpId","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/DumpUpvotedData.dumpId.html","deprecated":false},{"id":"namespace_dumpupvoteddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpUpvotedData.dumpTitle","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/DumpUpvotedData.dumpTitle.html","deprecated":false},{"id":"namespace_usermentioneddata","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UserMentionedData","file":"shared/notification.ts","doc":"Carried by a user_mentioned notification, sent to a user @mentioned in a comment, a dump, a playlist's description or a chat message, or to every user by a chat message's @everyone. Its DumpRef is the dump's, or the comment's dump's; its PlaylistRef the playlist's.","url":"./shared/notification.ts/~/UserMentionedData.html","deprecated":false},{"id":"namespace_usermentioneddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserMentionedData.mentionerId","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/UserMentionedData.mentionerId.html","deprecated":false},{"id":"namespace_usermentioneddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserMentionedData.mentionerUsername","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/UserMentionedData.mentionerUsername.html","deprecated":false},{"id":"namespace_usermentioneddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserMentionedData.contextType","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/UserMentionedData.contextType.html","deprecated":false},{"id":"namespace_usermentioneddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserMentionedData.contextId","file":"shared/notification.ts","doc":"The id of the comment, dump, playlist or chat message.","url":"./shared/notification.ts/~/UserMentionedData.contextId.html","deprecated":false},{"id":"namespace_usermentioneddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserMentionedData.contextTitle","file":"shared/notification.ts","doc":"The title of the dump or playlist, or of the dump a comment is under; empty for the chat.","url":"./shared/notification.ts/~/UserMentionedData.contextTitle.html","deprecated":false},{"id":"namespace_usermentioneddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserMentionedData.dumpId","file":"shared/notification.ts","doc":"Set only for a comment. It names the dump the comment is under, which the notification's link opens.","url":"./shared/notification.ts/~/UserMentionedData.dumpId.html","deprecated":false},{"id":"namespace_usermentioneddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserMentionedData.everyone","file":"shared/notification.ts","doc":"Set when the user was reached by @everyone rather than by name. A message naming them as well notifies them once, by name.","url":"./shared/notification.ts/~/UserMentionedData.everyone.html","deprecated":false},{"id":"namespace_dumpcommenteddata","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"DumpCommentedData","file":"shared/notification.ts","doc":"Carried by a dump_commented notification, sent to the dump's poster.","url":"./shared/notification.ts/~/DumpCommentedData.html","deprecated":false},{"id":"namespace_dumpcommenteddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpCommentedData.commenterId","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/DumpCommentedData.commenterId.html","deprecated":false},{"id":"namespace_dumpcommenteddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpCommentedData.commenterUsername","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/DumpCommentedData.commenterUsername.html","deprecated":false},{"id":"namespace_dumpcommenteddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpCommentedData.commentId","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/DumpCommentedData.commentId.html","deprecated":false},{"id":"namespace_dumpcommenteddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpCommentedData.dumpId","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/DumpCommentedData.dumpId.html","deprecated":false},{"id":"namespace_dumpcommenteddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpCommentedData.dumpTitle","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/DumpCommentedData.dumpTitle.html","deprecated":false},{"id":"namespace_commentlikeddata","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CommentLikedData","file":"shared/notification.ts","doc":"Carried by a comment_liked notification, sent to the comment's author.","url":"./shared/notification.ts/~/CommentLikedData.html","deprecated":false},{"id":"namespace_commentlikeddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentLikedData.likerId","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/CommentLikedData.likerId.html","deprecated":false},{"id":"namespace_commentlikeddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentLikedData.likerUsername","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/CommentLikedData.likerUsername.html","deprecated":false},{"id":"namespace_commentlikeddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentLikedData.commentId","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/CommentLikedData.commentId.html","deprecated":false},{"id":"namespace_commentlikeddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentLikedData.dumpId","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/CommentLikedData.dumpId.html","deprecated":false},{"id":"namespace_commentlikeddata","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentLikedData.dumpTitle","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/CommentLikedData.dumpTitle.html","deprecated":false},{"id":"namespace_notificationdata","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"NotificationData","file":"shared/notification.ts","doc":"Stored when the notification is made, so a title changed later still shows the old one. The …Username fields and the refs are joined when it is sent, so they follow a rename. The notification's type says which member it is.","url":"./shared/notification.ts/~/NotificationData.html","deprecated":false},{"id":"namespace_notification","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"Notification","file":"shared/notification.ts","doc":"Pushed to its user's sockets in a notification_created message when it is made, and returned by GET /api/me/notifications.","url":"./shared/notification.ts/~/Notification.html","deprecated":false},{"id":"namespace_notification","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Notification.id","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/Notification.id.html","deprecated":false},{"id":"namespace_notification","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Notification.userId","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/Notification.userId.html","deprecated":false},{"id":"namespace_notification","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Notification.type","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/Notification.type.html","deprecated":false},{"id":"namespace_notification","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Notification.data","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/Notification.data.html","deprecated":false},{"id":"namespace_notification","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Notification.read","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/Notification.read.html","deprecated":false},{"id":"namespace_notification","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Notification.createdAt","file":"shared/notification.ts","doc":"","url":"./shared/notification.ts/~/Notification.createdAt.html","deprecated":false},{"id":"namespace_feed_tabs","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"FEED_TABS","file":"shared/paths.ts","doc":"The feed tabs, in the tab bar's order. Each is a path segment: /hot for every dump, /music/hot for a category. They are reserved at the root, so no category can take one.","url":"./shared/paths.ts/~/FEED_TABS.html","deprecated":false},{"id":"namespace_feedtab","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"FeedTab","file":"shared/paths.ts","doc":"One of the FEED_TABS.","url":"./shared/paths.ts/~/FeedTab.html","deprecated":false},{"id":"namespace_profile_tabs","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"PROFILE_TABS","file":"shared/paths.ts","doc":"The tabs of a profile, each a segment after /@name. The bare /@name is the overview.","url":"./shared/paths.ts/~/PROFILE_TABS.html","deprecated":false},{"id":"namespace_profiletab","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"ProfileTab","file":"shared/paths.ts","doc":"One of the PROFILE_TABS.","url":"./shared/paths.ts/~/ProfileTab.html","deprecated":false},{"id":"namespace_follow_views","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"FOLLOW_VIEWS","file":"shared/paths.ts","doc":"The views of a follow tab, of what is followed: the users, at the bare tab, or the playlists. A profile's lists them, /@name/follow and /@name/follow/playlists, and a feed's shows their dumps, /follow and /follow/playlists.","url":"./shared/paths.ts/~/FOLLOW_VIEWS.html","deprecated":false},{"id":"namespace_followview","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"FollowView","file":"shared/paths.ts","doc":"One of the FOLLOW_VIEWS.","url":"./shared/paths.ts/~/FollowView.html","deprecated":false},{"id":"namespace_search_tabs","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"SEARCH_TABS","file":"shared/paths.ts","doc":"The tabs of the search page: the dumps at /search, the others at /search/<tab>.","url":"./shared/paths.ts/~/SEARCH_TABS.html","deprecated":false},{"id":"namespace_searchtab","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"SearchTab","file":"shared/paths.ts","doc":"One of the SEARCH_TABS.","url":"./shared/paths.ts/~/SearchTab.html","deprecated":false},{"id":"namespace_playlists_tabs","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"PLAYLISTS_TABS","file":"shared/paths.ts","doc":"The tabs of the playlists page, in the tab bar's order: each order of every public playlist, ?sort=, then the viewer's own playlists, ?mine=1, which only a signed-in user is offered.","url":"./shared/paths.ts/~/PLAYLISTS_TABS.html","deprecated":false},{"id":"namespace_playliststab","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"PlaylistsTab","file":"shared/paths.ts","doc":"One of the PLAYLISTS_TABS.","url":"./shared/paths.ts/~/PlaylistsTab.html","deprecated":false},{"id":"namespace_community_views","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"COMMUNITY_VIEWS","file":"shared/paths.ts","doc":"The views of the community page, one per digest cadence: the week at /community, the month at /community/monthly.","url":"./shared/paths.ts/~/COMMUNITY_VIEWS.html","deprecated":false},{"id":"namespace_owneditem","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"OwnedItem","file":"shared/paths.ts","doc":"Passed to dumpPath and playlistPath, usually as the item.","url":"./shared/paths.ts/~/OwnedItem.html","deprecated":false},{"id":"namespace_owneditem","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"OwnedItem.ownerUsername","file":"shared/paths.ts","doc":"","url":"./shared/paths.ts/~/OwnedItem.ownerUsername.html","deprecated":false},{"id":"namespace_owneditem","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"OwnedItem.slug","file":"shared/paths.ts","doc":"","url":"./shared/paths.ts/~/OwnedItem.slug.html","deprecated":false},{"id":"namespace_userpath","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"userPath","file":"shared/paths.ts","doc":"Returns the path of username's profile, of one of its tabs, or of a view of the follow tab. The default view, users, is the bare tab.","url":"./shared/paths.ts/~/userPath.html","deprecated":false},{"id":"namespace_dumppath","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"dumpPath","file":"shared/paths.ts","doc":"Returns the path of a dump's page, /@owner/dumps/<slug>, or of its editor, one segment more.","url":"./shared/paths.ts/~/dumpPath.html","deprecated":false},{"id":"namespace_playlistpath","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"playlistPath","file":"shared/paths.ts","doc":"Returns the path of a playlist's page, /@owner/playlists/<slug>, or of the page with its editor open, one segment more.","url":"./shared/paths.ts/~/playlistPath.html","deprecated":false},{"id":"namespace_feedpath","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"feedPath","file":"shared/paths.ts","doc":"Returns the path of a feed: every dump's at the root, or a category's at /<slug>, on tab, or on the viewer's default tab without one. The follow tab takes a view, the users followed by default.","url":"./shared/paths.ts/~/feedPath.html","deprecated":false},{"id":"namespace_playlistspath","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"playlistsPath","file":"shared/paths.ts","doc":"Returns the path of the page of every public playlist, /playlists, or of a playlist category's at /playlists/<slug>, on the tab tab names: an order, the default one without it, or the viewer's own playlists.","url":"./shared/paths.ts/~/playlistsPath.html","deprecated":false},{"id":"namespace_parseplayliststab","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"parsePlaylistsTab","file":"shared/paths.ts","doc":"Returns the tab of the playlists page its query names: the viewer's own playlists with a mine, else the order sort names, as parsePlaylistSort reads it.","url":"./shared/paths.ts/~/parsePlaylistsTab.html","deprecated":false},{"id":"namespace_playlistsortquery","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"playlistSortQuery","file":"shared/paths.ts","doc":"Returns the query string that puts a list of playlists in the order sort names, with its ?, or \"\" for the default order. extra holds the list's other parameters, such as a profile's category.","url":"./shared/paths.ts/~/playlistSortQuery.html","deprecated":false},{"id":"namespace_categorypath","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"categoryPath","file":"shared/paths.ts","doc":"Returns the path of the page of the category of kind at slug: a dump category's feed (feedPath), or a playlist category's playlists (playlistsPath). The category chips link to it.","url":"./shared/paths.ts/~/categoryPath.html","deprecated":false},{"id":"namespace_searchpath","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"searchPath","file":"shared/paths.ts","doc":"Returns the path of the search page on tab, searching query when it is given.","url":"./shared/paths.ts/~/searchPath.html","deprecated":false},{"id":"namespace_communitypath","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"communityPath","file":"shared/paths.ts","doc":"Returns the path of the community page on view, the week by default.","url":"./shared/paths.ts/~/communityPath.html","deprecated":false},{"id":"namespace_pagepath","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"PagePath","file":"shared/paths.ts","doc":"Returned by parsePagePath for a path under a user. rest holds the segments after /@name, a profile tab and its view.","url":"./shared/paths.ts/~/PagePath.html","deprecated":false},{"id":"namespace_parsepagepath","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"parsePagePath","file":"shared/paths.ts","doc":"Returns what a page path under a user names: a profile (with its tab), a dump or a playlist (or its editor). It returns null for any other path, a feed or an app page, and for one under a user that no page answers. The names are decoded but not looked up, so the user or the item may not exist.","url":"./shared/paths.ts/~/parsePagePath.html","deprecated":false},{"id":"namespace_permission","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"Permission","file":"shared/permissions.ts","doc":"An action only some roles may take. A new one goes in this union and in ALL_PERMISSIONS, which is what grants it to admins.","url":"./shared/permissions.ts/~/Permission.html","deprecated":false},{"id":"namespace_role_permissions","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"ROLE_PERMISSIONS","file":"shared/permissions.ts","doc":"Read through hasPermission. Roles are fixed in code. An admin holds every permission, and a moderator the moderation ones and @everyone in the chat.","url":"./shared/permissions.ts/~/ROLE_PERMISSIONS.html","deprecated":false},{"id":"namespace_haspermission","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"hasPermission","file":"shared/permissions.ts","doc":"Checks whether role grants permission. The server's can and the client's can both wrap it.","url":"./shared/permissions.ts/~/hasPermission.html","deprecated":false},{"id":"namespace_tralbumtrack","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"TralbumTrack","file":"shared/player.ts","doc":"Listed by a Tralbum, in the release's order.","url":"./shared/player.ts/~/TralbumTrack.html","deprecated":false},{"id":"namespace_tralbumtrack","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TralbumTrack.index","file":"shared/player.ts","doc":"The track's position in the release's list. The player keeps it, with the page URL, to resolve the track again once its stream URL expires.","url":"./shared/player.ts/~/TralbumTrack.index.html","deprecated":false},{"id":"namespace_tralbumtrack","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TralbumTrack.trackNum","file":"shared/player.ts","doc":"","url":"./shared/player.ts/~/TralbumTrack.trackNum.html","deprecated":false},{"id":"namespace_tralbumtrack","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TralbumTrack.title","file":"shared/player.ts","doc":"","url":"./shared/player.ts/~/TralbumTrack.title.html","deprecated":false},{"id":"namespace_tralbumtrack","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TralbumTrack.duration","file":"shared/player.ts","doc":"In seconds, with a fraction.","url":"./shared/player.ts/~/TralbumTrack.duration.html","deprecated":false},{"id":"namespace_tralbumtrack","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TralbumTrack.streamUrl","file":"shared/player.ts","doc":"A signed URL that expires. Null when the track can't be played.","url":"./shared/player.ts/~/TralbumTrack.streamUrl.html","deprecated":false},{"id":"namespace_tralbumtrack","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TralbumTrack.streamable","file":"shared/player.ts","doc":"False for preorder, unreleased and still-encoding tracks. They stay in the list so that the numbering matches the release, but the player skips them.","url":"./shared/player.ts/~/TralbumTrack.streamable.html","deprecated":false},{"id":"namespace_tralbumtrack","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TralbumTrack.capped","file":"shared/player.ts","doc":"Set when Bandcamp capped its free plays, so it may serve only a clip.","url":"./shared/player.ts/~/TralbumTrack.capped.html","deprecated":false},{"id":"namespace_tralbum","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"Tralbum","file":"shared/player.ts","doc":"Returned by GET /api/remote/bandcamp for a Bandcamp album or track page, when the native player plays it.","url":"./shared/player.ts/~/Tralbum.html","deprecated":false},{"id":"namespace_tralbum","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Tralbum.sourceUrl","file":"shared/player.ts","doc":"","url":"./shared/player.ts/~/Tralbum.sourceUrl.html","deprecated":false},{"id":"namespace_tralbum","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Tralbum.itemType","file":"shared/player.ts","doc":"","url":"./shared/player.ts/~/Tralbum.itemType.html","deprecated":false},{"id":"namespace_tralbum","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Tralbum.title","file":"shared/player.ts","doc":"","url":"./shared/player.ts/~/Tralbum.title.html","deprecated":false},{"id":"namespace_tralbum","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Tralbum.artist","file":"shared/player.ts","doc":"","url":"./shared/player.ts/~/Tralbum.artist.html","deprecated":false},{"id":"namespace_tralbum","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Tralbum.artworkUrl","file":"shared/player.ts","doc":"","url":"./shared/player.ts/~/Tralbum.artworkUrl.html","deprecated":false},{"id":"namespace_tralbum","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Tralbum.tracks","file":"shared/player.ts","doc":"","url":"./shared/player.ts/~/Tralbum.tracks.html","deprecated":false},{"id":"namespace_tralbum","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Tralbum.resolvedAt","file":"shared/player.ts","doc":"When the stream URLs were fetched, in epoch ms. The player resolves the page again once they are old enough to have expired.","url":"./shared/player.ts/~/Tralbum.resolvedAt.html","deprecated":false},{"id":"namespace_youtubeplaylisttrack","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"YouTubePlaylistTrack","file":"shared/player.ts","doc":"Listed by a YouTubePlaylist, in the playlist's order.","url":"./shared/player.ts/~/YouTubePlaylistTrack.html","deprecated":false},{"id":"namespace_youtubeplaylisttrack","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"YouTubePlaylistTrack.videoId","file":"shared/player.ts","doc":"","url":"./shared/player.ts/~/YouTubePlaylistTrack.videoId.html","deprecated":false},{"id":"namespace_youtubeplaylisttrack","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"YouTubePlaylistTrack.title","file":"shared/player.ts","doc":"","url":"./shared/player.ts/~/YouTubePlaylistTrack.title.html","deprecated":false},{"id":"namespace_youtubeplaylisttrack","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"YouTubePlaylistTrack.duration","file":"shared/player.ts","doc":"In seconds.","url":"./shared/player.ts/~/YouTubePlaylistTrack.duration.html","deprecated":false},{"id":"namespace_youtubeplaylist","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"YouTubePlaylist","file":"shared/player.ts","doc":"Returned by GET /api/remote/youtube to the player, which shows the titles and lengths of a playlist embed's videos, since the embed exposes neither.","url":"./shared/player.ts/~/YouTubePlaylist.html","deprecated":false},{"id":"namespace_youtubeplaylist","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"YouTubePlaylist.listId","file":"shared/player.ts","doc":"","url":"./shared/player.ts/~/YouTubePlaylist.listId.html","deprecated":false},{"id":"namespace_youtubeplaylist","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"YouTubePlaylist.title","file":"shared/player.ts","doc":"","url":"./shared/player.ts/~/YouTubePlaylist.title.html","deprecated":false},{"id":"namespace_youtubeplaylist","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"YouTubePlaylist.tracks","file":"shared/player.ts","doc":"","url":"./shared/player.ts/~/YouTubePlaylist.tracks.html","deprecated":false},{"id":"namespace_playlist_sorts","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"PLAYLIST_SORTS","file":"shared/playlist.ts","doc":"The orders a list of playlists comes in, the first being the default one: updated, by playlistActivity, the latest first; new, by creation, the newest first; dumps, the fullest first. GET /api/playlists and GET /api/users/:key/playlists take one as ?sort=, the /playlists page and a profile's playlists tab show them as tabs and keep the one picked in their URL's ?sort=.","url":"./shared/playlist.ts/~/PLAYLIST_SORTS.html","deprecated":false},{"id":"namespace_playlistsort","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"PlaylistSort","file":"shared/playlist.ts","doc":"One of the PLAYLIST_SORTS.","url":"./shared/playlist.ts/~/PlaylistSort.html","deprecated":false},{"id":"namespace_parseplaylistsort","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"parsePlaylistSort","file":"shared/playlist.ts","doc":"Returns the order a ?sort= names, the default one when it is missing or names none: like a page number, an order never fails a list.","url":"./shared/playlist.ts/~/parsePlaylistSort.html","deprecated":false},{"id":"namespace_playlist","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"Playlist","file":"shared/playlist.ts","doc":"Returned by the playlist routes, and by the search, users and dumps routes that list playlists. The playlist_created and playlist_updated WebSocket messages carry it too.","url":"./shared/playlist.ts/~/Playlist.html","deprecated":false},{"id":"namespace_playlist","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Playlist.id","file":"shared/playlist.ts","doc":"","url":"./shared/playlist.ts/~/Playlist.id.html","deprecated":false},{"id":"namespace_playlist","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Playlist.userId","file":"shared/playlist.ts","doc":"","url":"./shared/playlist.ts/~/Playlist.userId.html","deprecated":false},{"id":"namespace_playlist","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Playlist.title","file":"shared/playlist.ts","doc":"","url":"./shared/playlist.ts/~/Playlist.title.html","deprecated":false},{"id":"namespace_playlist","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Playlist.slug","file":"shared/playlist.ts","doc":"Names the playlist in its page's path, playlistPath (shared/paths.ts) building it with ownerUsername. Made from the title on creation, it changes only when edited, and is unique among its owner's playlists.","url":"./shared/playlist.ts/~/Playlist.slug.html","deprecated":false},{"id":"namespace_playlist","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Playlist.description","file":"shared/playlist.ts","doc":"It is written in Markdown.","url":"./shared/playlist.ts/~/Playlist.description.html","deprecated":false},{"id":"namespace_playlist","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Playlist.isPublic","file":"shared/playlist.ts","doc":"Only its owner sees a private playlist. Moderators don't, though they may still edit or delete it.","url":"./shared/playlist.ts/~/Playlist.isPublic.html","deprecated":false},{"id":"namespace_playlist","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Playlist.createdAt","file":"shared/playlist.ts","doc":"","url":"./shared/playlist.ts/~/Playlist.createdAt.html","deprecated":false},{"id":"namespace_playlist","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Playlist.updatedAt","file":"shared/playlist.ts","doc":"playlistImageUrl puts it on the cover's URL, so a new cover isn't hidden by the cached old one.","url":"./shared/playlist.ts/~/Playlist.updatedAt.html","deprecated":false},{"id":"namespace_playlist","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Playlist.imageMime","file":"shared/playlist.ts","doc":"It is undefined when the playlist has no cover.","url":"./shared/playlist.ts/~/Playlist.imageMime.html","deprecated":false},{"id":"namespace_playlist","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Playlist.dumpCount","file":"shared/playlist.ts","doc":"It counts the dumps the viewer may see in it, as its page lists them. It is undefined when the query didn't count them.","url":"./shared/playlist.ts/~/Playlist.dumpCount.html","deprecated":false},{"id":"namespace_playlist","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Playlist.lastDumpAt","file":"shared/playlist.ts","doc":"When the latest of the dumps the viewer may see was added to it, which playlistActivity reads. It is undefined when it holds none, or when the query didn't count them.","url":"./shared/playlist.ts/~/Playlist.lastDumpAt.html","deprecated":false},{"id":"namespace_playlist","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Playlist.ownerUsername","file":"shared/playlist.ts","doc":"The owner's current name, which the playlist's path starts with.","url":"./shared/playlist.ts/~/Playlist.ownerUsername.html","deprecated":false},{"id":"namespace_playlist","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Playlist.categoryIds","file":"shared/playlist.ts","doc":"The ids of the playlist categories it is filed under. The services fill them in on every playlist they return.","url":"./shared/playlist.ts/~/Playlist.categoryIds.html","deprecated":false},{"id":"namespace_playlistactivity","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"playlistActivity","file":"shared/playlist.ts","doc":"Returns when playlist last took a dump, or was created if it holds none: what the updated order sorts by and the cards show. Its title, cover and description may change after without bringing it back up a list.","url":"./shared/playlist.ts/~/playlistActivity.html","deprecated":false},{"id":"namespace_compareplaylists","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"comparePlaylists","file":"shared/playlist.ts","doc":"Returns the comparison that puts playlists in the order sort names, as the API pages them, the newer first on a tie. usePlaylistListSync finds with it where a playlist the socket announces goes in a list.","url":"./shared/playlist.ts/~/comparePlaylists.html","deprecated":false},{"id":"namespace_playlistwithdumps","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PlaylistWithDumps","file":"shared/playlist.ts","doc":"Returned by GET /api/users/:key/playlists/:slug to PlaylistDetail, and by GET /api/playlists/:playlistId, with the dumps the caller may see, in the playlist's order.","url":"./shared/playlist.ts/~/PlaylistWithDumps.html","deprecated":false},{"id":"namespace_playlistwithdumps","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistWithDumps.dumps","file":"shared/playlist.ts","doc":"","url":"./shared/playlist.ts/~/PlaylistWithDumps.dumps.html","deprecated":false},{"id":"namespace_playlistmembership","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PlaylistMembership","file":"shared/playlist.ts","doc":"Returned by GET /api/me/playlists?contains=:dumpId, one per playlist of the caller's. PlaylistMembershipPanel ticks the playlists with hasDump, in the add-to-playlist modal and the dump form.","url":"./shared/playlist.ts/~/PlaylistMembership.html","deprecated":false},{"id":"namespace_playlistmembership","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistMembership.playlist","file":"shared/playlist.ts","doc":"","url":"./shared/playlist.ts/~/PlaylistMembership.playlist.html","deprecated":false},{"id":"namespace_playlistmembership","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistMembership.hasDump","file":"shared/playlist.ts","doc":"","url":"./shared/playlist.ts/~/PlaylistMembership.hasDump.html","deprecated":false},{"id":"namespace_createplaylistrequest","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CreatePlaylistRequest","file":"shared/playlist.ts","doc":"Passed to POST /api/playlists by PlaylistCreateForm.","url":"./shared/playlist.ts/~/CreatePlaylistRequest.html","deprecated":false},{"id":"namespace_createplaylistrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CreatePlaylistRequest.title","file":"shared/playlist.ts","doc":"","url":"./shared/playlist.ts/~/CreatePlaylistRequest.title.html","deprecated":false},{"id":"namespace_createplaylistrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CreatePlaylistRequest.description","file":"shared/playlist.ts","doc":"","url":"./shared/playlist.ts/~/CreatePlaylistRequest.description.html","deprecated":false},{"id":"namespace_createplaylistrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CreatePlaylistRequest.isPublic","file":"shared/playlist.ts","doc":"","url":"./shared/playlist.ts/~/CreatePlaylistRequest.isPublic.html","deprecated":false},{"id":"namespace_createplaylistrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CreatePlaylistRequest.categoryIds","file":"shared/playlist.ts","doc":"The playlist categories to file it under, none when left out.","url":"./shared/playlist.ts/~/CreatePlaylistRequest.categoryIds.html","deprecated":false},{"id":"namespace_updateplaylistrequest","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UpdatePlaylistRequest","file":"shared/playlist.ts","doc":"Passed to PUT /api/playlists/:playlistId by PlaylistDetail. A field left out keeps its value.","url":"./shared/playlist.ts/~/UpdatePlaylistRequest.html","deprecated":false},{"id":"namespace_updateplaylistrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UpdatePlaylistRequest.title","file":"shared/playlist.ts","doc":"","url":"./shared/playlist.ts/~/UpdatePlaylistRequest.title.html","deprecated":false},{"id":"namespace_updateplaylistrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UpdatePlaylistRequest.slug","file":"shared/playlist.ts","doc":"A new slug, which the edit form's slug field sends. A title change never changes the slug by itself.","url":"./shared/playlist.ts/~/UpdatePlaylistRequest.slug.html","deprecated":false},{"id":"namespace_updateplaylistrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UpdatePlaylistRequest.description","file":"shared/playlist.ts","doc":"null removes the description.","url":"./shared/playlist.ts/~/UpdatePlaylistRequest.description.html","deprecated":false},{"id":"namespace_updateplaylistrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UpdatePlaylistRequest.isPublic","file":"shared/playlist.ts","doc":"","url":"./shared/playlist.ts/~/UpdatePlaylistRequest.isPublic.html","deprecated":false},{"id":"namespace_updateplaylistrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UpdatePlaylistRequest.categoryIds","file":"shared/playlist.ts","doc":"Replaces its playlist categories; [] takes it out of every one.","url":"./shared/playlist.ts/~/UpdatePlaylistRequest.categoryIds.html","deprecated":false},{"id":"namespace_reorderplaylistrequest","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ReorderPlaylistRequest","file":"shared/playlist.ts","doc":"Passed to PUT /api/playlists/:playlistId/order by PlaylistDetail, after a drag or to put back a dump whose removal was undone.","url":"./shared/playlist.ts/~/ReorderPlaylistRequest.html","deprecated":false},{"id":"namespace_reorderplaylistrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ReorderPlaylistRequest.dumpIds","file":"shared/playlist.ts","doc":"Every dump of the playlist the caller can see, in the new order. The dumps hidden from them keep their slots.","url":"./shared/playlist.ts/~/ReorderPlaylistRequest.dumpIds.html","deprecated":false},{"id":"namespace_searchresults","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"SearchResults","file":"shared/search.ts","doc":"Returned by GET /api/search to the Search page. Only the dumps are paged, and each page brings the users and playlists again.","url":"./shared/search.ts/~/SearchResults.html","deprecated":false},{"id":"namespace_searchresults","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SearchResults.dumps","file":"shared/search.ts","doc":"It always has its total, which the page shows in the dumps tab's label.","url":"./shared/search.ts/~/SearchResults.dumps.html","deprecated":false},{"id":"namespace_searchresults","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SearchResults.users","file":"shared/search.ts","doc":"There are 20 at most.","url":"./shared/search.ts/~/SearchResults.users.html","deprecated":false},{"id":"namespace_searchresults","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SearchResults.playlists","file":"shared/search.ts","doc":"There are 20 at most.","url":"./shared/search.ts/~/SearchResults.playlists.html","deprecated":false},{"id":"namespace_usersettings","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UserSettings","file":"shared/settings.ts","doc":"Returned by GET /api/me/settings, and by a PATCH once applied. The client's useSettings reads it from the session.","url":"./shared/settings.ts/~/UserSettings.html","deprecated":false},{"id":"namespace_usersettings","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserSettings.style","file":"shared/settings.ts","doc":"Null until the user picks one, so the instance's default style (GERBEUR_DEFAULT_STYLE) applies, and so a browser's earlier choice can be carried over on first sign-in.","url":"./shared/settings.ts/~/UserSettings.style.html","deprecated":false},{"id":"namespace_usersettings","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserSettings.colorScheme","file":"shared/settings.ts","doc":"Null until the user picks one, which reads as \"auto\".","url":"./shared/settings.ts/~/UserSettings.colorScheme.html","deprecated":false},{"id":"namespace_usersettings","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserSettings.digestWeekly","file":"shared/settings.ts","doc":"Whether the weekly digest is sent.","url":"./shared/settings.ts/~/UserSettings.digestWeekly.html","deprecated":false},{"id":"namespace_usersettings","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserSettings.digestMonthly","file":"shared/settings.ts","doc":"Whether the monthly recap is sent.","url":"./shared/settings.ts/~/UserSettings.digestMonthly.html","deprecated":false},{"id":"namespace_updatesettingsrequest","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"UpdateSettingsRequest","file":"shared/settings.ts","doc":"Sent to PATCH /api/me/settings with the settings to change; the others keep their value.","url":"./shared/settings.ts/~/UpdateSettingsRequest.html","deprecated":false},{"id":"namespace_default_settings","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"DEFAULT_SETTINGS","file":"shared/settings.ts","doc":"The settings of a user who never changed any. Digests are on by default.","url":"./shared/settings.ts/~/DEFAULT_SETTINGS.html","deprecated":false},{"id":"namespace_digest_cadences","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"DIGEST_CADENCES","file":"shared/settings.ts","doc":"Lists how often a digest can come: weekly, or monthly as a recap.","url":"./shared/settings.ts/~/DIGEST_CADENCES.html","deprecated":false},{"id":"namespace_digestcadence","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"DigestCadence","file":"shared/settings.ts","doc":"One of the DIGEST_CADENCES. An unsubscribe link names one, which turns off its setting alone.","url":"./shared/settings.ts/~/DigestCadence.html","deprecated":false},{"id":"namespace_period_ms","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"PERIOD_MS","file":"shared/settings.ts","doc":"How long each cadence's period lasts, rolling: a digest covers the one just ended, and the /community page the one ending now.","url":"./shared/settings.ts/~/PERIOD_MS.html","deprecated":false},{"id":"namespace_isdigestcadence","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isDigestCadence","file":"shared/settings.ts","doc":"Checks whether value is a DigestCadence.","url":"./shared/settings.ts/~/isDigestCadence.html","deprecated":false},{"id":"namespace_digest_setting","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"DIGEST_SETTING","file":"shared/settings.ts","doc":"Names the setting that switches each cadence of digest.","url":"./shared/settings.ts/~/DIGEST_SETTING.html","deprecated":false},{"id":"namespace_slug_max","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"SLUG_MAX","file":"shared/slug.ts","doc":"The longest a dump's or a playlist's slug may be.","url":"./shared/slug.ts/~/SLUG_MAX.html","deprecated":false},{"id":"namespace_slug_re","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"SLUG_RE","file":"shared/slug.ts","doc":"Matches a well-formed slug: lowercase letters and digits, in words joined by single hyphens. Categories, dumps and playlists share it.","url":"./shared/slug.ts/~/SLUG_RE.html","deprecated":false},{"id":"namespace_isvalidslug","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isValidSlug","file":"shared/slug.ts","doc":"Checks whether slug matches SLUG_RE and is at most max characters long.","url":"./shared/slug.ts/~/isValidSlug.html","deprecated":false},{"id":"namespace_slugify","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"slugify","file":"shared/slug.ts","doc":"Turns title into lowercase ASCII words joined by hyphens, at most max characters long, cut at a hyphen when it must be cut. Accents are dropped, and a title with no ASCII letter or digit gives untitled. The result always passes isValidSlug.","url":"./shared/slug.ts/~/slugify.html","deprecated":false},{"id":"namespace_style_names","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"STYLE_NAMES","file":"shared/theme.ts","doc":"Lists every site style. Each has a stylesheet under src/themes/, keyed on the root element's data-style, and an email style in api/mail/styles.ts read from that stylesheet.","url":"./shared/theme.ts/~/STYLE_NAMES.html","deprecated":false},{"id":"namespace_stylename","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"StyleName","file":"shared/theme.ts","doc":"One of the STYLE_NAMES.","url":"./shared/theme.ts/~/StyleName.html","deprecated":false},{"id":"namespace_base_style","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"BASE_STYLE","file":"shared/theme.ts","doc":"The style the stylesheets draw when the root element has no data-style, and the one an unset or unknown GERBEUR_DEFAULT_STYLE means.","url":"./shared/theme.ts/~/BASE_STYLE.html","deprecated":false},{"id":"namespace_color_schemes","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"COLOR_SCHEMES","file":"shared/theme.ts","doc":"Lists every color scheme. \"auto\" follows the system's.","url":"./shared/theme.ts/~/COLOR_SCHEMES.html","deprecated":false},{"id":"namespace_colorscheme","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"ColorScheme","file":"shared/theme.ts","doc":"One of the COLOR_SCHEMES.","url":"./shared/theme.ts/~/ColorScheme.html","deprecated":false},{"id":"namespace_default_color_scheme","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"DEFAULT_COLOR_SCHEME","file":"shared/theme.ts","doc":"The scheme of whoever hasn't picked one: the system's.","url":"./shared/theme.ts/~/DEFAULT_COLOR_SCHEME.html","deprecated":false},{"id":"namespace_isstylename","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isStyleName","file":"shared/theme.ts","doc":"Checks whether value is a StyleName, as a stored choice or an environment variable must be before it is applied.","url":"./shared/theme.ts/~/isStyleName.html","deprecated":false},{"id":"namespace_iscolorscheme","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isColorScheme","file":"shared/theme.ts","doc":"Checks whether value is a ColorScheme.","url":"./shared/theme.ts/~/isColorScheme.html","deprecated":false},{"id":"namespace_sitehostof","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"siteHostOf","file":"shared/url.ts","doc":"Returns url's host without a leading www.; URL has already lowered its case. www.youtube.com and youtube.com give youtube.com.","url":"./shared/url.ts/~/siteHostOf.html","deprecated":false},{"id":"namespace_sitehost","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"siteHost","file":"shared/url.ts","doc":"Returns siteHostOf the URL raw, or undefined when raw isn't one.","url":"./shared/url.ts/~/siteHost.html","deprecated":false},{"id":"namespace_role","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"Role","file":"shared/user.ts","doc":"Sets what a user may do beyond the basics, through ROLE_PERMISSIONS (shared/permissions.ts). An admin changes it with PATCH /api/users/:key/role.","url":"./shared/user.ts/~/Role.html","deprecated":false},{"id":"namespace_roles","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"ROLES","file":"shared/user.ts","doc":"Every Role, least to most privileged.","url":"./shared/user.ts/~/ROLES.html","deprecated":false},{"id":"namespace_isrole","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isRole","file":"shared/user.ts","doc":"Checks whether value is a Role, as the role endpoint and the row guards must before trusting one.","url":"./shared/user.ts/~/isRole.html","deprecated":false},{"id":"namespace_publicuser","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PublicUser","file":"shared/user.ts","doc":"Returned by every endpoint that shows a user to others: profiles, the users one follows, search results, and the user_updated socket message. The server makes it with toPublicUser, which drops the email.","url":"./shared/user.ts/~/PublicUser.html","deprecated":false},{"id":"namespace_publicuser","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PublicUser.id","file":"shared/user.ts","doc":"","url":"./shared/user.ts/~/PublicUser.id.html","deprecated":false},{"id":"namespace_publicuser","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PublicUser.username","file":"shared/user.ts","doc":"Picked at sign-up, and changeable since, a former name staying an alias of the user for good. Pages write it as @name (userPath).","url":"./shared/user.ts/~/PublicUser.username.html","deprecated":false},{"id":"namespace_publicuser","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PublicUser.role","file":"shared/user.ts","doc":"","url":"./shared/user.ts/~/PublicUser.role.html","deprecated":false},{"id":"namespace_publicuser","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PublicUser.createdAt","file":"shared/user.ts","doc":"","url":"./shared/user.ts/~/PublicUser.createdAt.html","deprecated":false},{"id":"namespace_publicuser","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PublicUser.updatedAt","file":"shared/user.ts","doc":"Bumped by any profile or avatar change. The client uses it to reload the avatar.","url":"./shared/user.ts/~/PublicUser.updatedAt.html","deprecated":false},{"id":"namespace_publicuser","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PublicUser.avatarMime","file":"shared/user.ts","doc":"Undefined without an avatar.","url":"./shared/user.ts/~/PublicUser.avatarMime.html","deprecated":false},{"id":"namespace_publicuser","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PublicUser.description","file":"shared/user.ts","doc":"Markdown.","url":"./shared/user.ts/~/PublicUser.description.html","deprecated":false},{"id":"namespace_publicuser","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PublicUser.invitedByUsername","file":"shared/user.ts","doc":"","url":"./shared/user.ts/~/PublicUser.invitedByUsername.html","deprecated":false},{"id":"namespace_selfuser","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"SelfUser","file":"shared/user.ts","doc":"Returned to a user about themselves: by sign-up and sign-in in AuthResponse, by GET /api/me, and by an avatar upload.","url":"./shared/user.ts/~/SelfUser.html","deprecated":false},{"id":"namespace_selfuser","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SelfUser.email","file":"shared/user.ts","doc":"Where password reset links go. It belongs to this account only.","url":"./shared/user.ts/~/SelfUser.email.html","deprecated":false},{"id":"namespace_usersuggestion","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UserSuggestion","file":"shared/user.ts","doc":"Returned by GET /api/users?q= to the editor's @mention autocomplete.","url":"./shared/user.ts/~/UserSuggestion.html","deprecated":false},{"id":"namespace_usersuggestion","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserSuggestion.id","file":"shared/user.ts","doc":"","url":"./shared/user.ts/~/UserSuggestion.id.html","deprecated":false},{"id":"namespace_usersuggestion","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserSuggestion.username","file":"shared/user.ts","doc":"","url":"./shared/user.ts/~/UserSuggestion.username.html","deprecated":false},{"id":"namespace_usersuggestion","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserSuggestion.avatarMime","file":"shared/user.ts","doc":"Null without an avatar.","url":"./shared/user.ts/~/UserSuggestion.avatarMime.html","deprecated":false},{"id":"namespace_invitee","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"Invitee","file":"shared/user.ts","doc":"Returned, as a flat list in sign-up order, by GET /api/users/:key/invitees. The profile page nests it into a tree by invitedById.","url":"./shared/user.ts/~/Invitee.html","deprecated":false},{"id":"namespace_invitee","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Invitee.id","file":"shared/user.ts","doc":"","url":"./shared/user.ts/~/Invitee.id.html","deprecated":false},{"id":"namespace_invitee","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Invitee.username","file":"shared/user.ts","doc":"","url":"./shared/user.ts/~/Invitee.username.html","deprecated":false},{"id":"namespace_invitee","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Invitee.avatarMime","file":"shared/user.ts","doc":"Undefined without an avatar.","url":"./shared/user.ts/~/Invitee.avatarMime.html","deprecated":false},{"id":"namespace_invitee","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Invitee.invitedById","file":"shared/user.ts","doc":"","url":"./shared/user.ts/~/Invitee.invitedById.html","deprecated":false},{"id":"namespace_invitee","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Invitee.createdAt","file":"shared/user.ts","doc":"","url":"./shared/user.ts/~/Invitee.createdAt.html","deprecated":false},{"id":"namespace_loginuserrequest","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"LoginUserRequest","file":"shared/user.ts","doc":"Sent to POST /api/sessions by the login page.","url":"./shared/user.ts/~/LoginUserRequest.html","deprecated":false},{"id":"namespace_loginuserrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"LoginUserRequest.username","file":"shared/user.ts","doc":"","url":"./shared/user.ts/~/LoginUserRequest.username.html","deprecated":false},{"id":"namespace_loginuserrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"LoginUserRequest.password","file":"shared/user.ts","doc":"","url":"./shared/user.ts/~/LoginUserRequest.password.html","deprecated":false},{"id":"namespace_registeruserrequest","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"RegisterUserRequest","file":"shared/user.ts","doc":"Sent to POST /api/users by the register page.","url":"./shared/user.ts/~/RegisterUserRequest.html","deprecated":false},{"id":"namespace_registeruserrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RegisterUserRequest.username","file":"shared/user.ts","doc":"","url":"./shared/user.ts/~/RegisterUserRequest.username.html","deprecated":false},{"id":"namespace_registeruserrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RegisterUserRequest.password","file":"shared/user.ts","doc":"","url":"./shared/user.ts/~/RegisterUserRequest.password.html","deprecated":false},{"id":"namespace_registeruserrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RegisterUserRequest.inviteToken","file":"shared/user.ts","doc":"From the invite link the register page was opened with.","url":"./shared/user.ts/~/RegisterUserRequest.inviteToken.html","deprecated":false},{"id":"namespace_registeruserrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RegisterUserRequest.email","file":"shared/user.ts","doc":"","url":"./shared/user.ts/~/RegisterUserRequest.email.html","deprecated":false},{"id":"namespace_updateuserrequest","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UpdateUserRequest","file":"shared/user.ts","doc":"Passed to updateUser by the users routes and the password reset, and sent by a client to PATCH /api/me, which takes only description and email; the role and the password change through their own endpoints, and the username through renameUser, by a moderator only.","url":"./shared/user.ts/~/UpdateUserRequest.html","deprecated":false},{"id":"namespace_updateuserrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UpdateUserRequest.password","file":"shared/user.ts","doc":"","url":"./shared/user.ts/~/UpdateUserRequest.password.html","deprecated":false},{"id":"namespace_updateuserrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UpdateUserRequest.role","file":"shared/user.ts","doc":"","url":"./shared/user.ts/~/UpdateUserRequest.role.html","deprecated":false},{"id":"namespace_updateuserrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UpdateUserRequest.description","file":"shared/user.ts","doc":"An empty string clears it. Null, like undefined, keeps it.","url":"./shared/user.ts/~/UpdateUserRequest.description.html","deprecated":false},{"id":"namespace_updateuserrequest","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UpdateUserRequest.email","file":"shared/user.ts","doc":"","url":"./shared/user.ts/~/UpdateUserRequest.email.html","deprecated":false},{"id":"namespace_authtokens","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"AuthTokens","file":"shared/user.ts","doc":"Returned by sign-up, sign-in and a password change. The client keeps both tokens with its session.","url":"./shared/user.ts/~/AuthTokens.html","deprecated":false},{"id":"namespace_authtokens","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AuthTokens.token","file":"shared/user.ts","doc":"Sent as Authorization: Bearer …, and as ?token= to the WebSocket.","url":"./shared/user.ts/~/AuthTokens.token.html","deprecated":false},{"id":"namespace_authtokens","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AuthTokens.mediaToken","file":"shared/user.ts","doc":"Carried as ?token= by the URLs of private media. It can read media and nothing else.","url":"./shared/user.ts/~/AuthTokens.mediaToken.html","deprecated":false},{"id":"namespace_authresponse","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"AuthResponse","file":"shared/user.ts","doc":"Returned by sign-up and sign-in.","url":"./shared/user.ts/~/AuthResponse.html","deprecated":false},{"id":"namespace_authresponse","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AuthResponse.user","file":"shared/user.ts","doc":"","url":"./shared/user.ts/~/AuthResponse.user.html","deprecated":false},{"id":"namespace_mediatokenresponse","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"MediaTokenResponse","file":"shared/user.ts","doc":"Returned by GET /api/me/media-token to a session from before media tokens, which has none.","url":"./shared/user.ts/~/MediaTokenResponse.html","deprecated":false},{"id":"namespace_inviteresponse","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"InviteResponse","file":"shared/user.ts","doc":"Returned by POST /api/invites to the profile page, which builds the invite link from token.","url":"./shared/user.ts/~/InviteResponse.html","deprecated":false},{"id":"namespace_inviteresponse","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InviteResponse.token","file":"shared/user.ts","doc":"","url":"./shared/user.ts/~/InviteResponse.token.html","deprecated":false},{"id":"namespace_validation","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"VALIDATION","file":"shared/validation.ts","doc":"Read by the validators and services, which refuse what breaks a limit, and by the forms, which say so before sending. Lengths are JavaScript string lengths, so an emoji may count for two. The category limits are checked on the server only.","url":"./shared/validation.ts/~/VALIDATION.html","deprecated":false},{"id":"namespace_validation","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VALIDATION.USERNAME_MIN","file":"shared/validation.ts","doc":"","url":"./shared/validation.ts/~/VALIDATION.USERNAME_MIN.html","deprecated":false},{"id":"namespace_validation","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VALIDATION.USERNAME_MAX","file":"shared/validation.ts","doc":"","url":"./shared/validation.ts/~/VALIDATION.USERNAME_MAX.html","deprecated":false},{"id":"namespace_validation","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VALIDATION.PASSWORD_MIN","file":"shared/validation.ts","doc":"","url":"./shared/validation.ts/~/VALIDATION.PASSWORD_MIN.html","deprecated":false},{"id":"namespace_validation","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VALIDATION.PASSWORD_MAX","file":"shared/validation.ts","doc":"","url":"./shared/validation.ts/~/VALIDATION.PASSWORD_MAX.html","deprecated":false},{"id":"namespace_validation","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VALIDATION.DUMP_TITLE_MAX","file":"shared/validation.ts","doc":"","url":"./shared/validation.ts/~/VALIDATION.DUMP_TITLE_MAX.html","deprecated":false},{"id":"namespace_validation","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VALIDATION.DUMP_COMMENT_MAX","file":"shared/validation.ts","doc":"Applies to a dump's note, which the API calls its comment.","url":"./shared/validation.ts/~/VALIDATION.DUMP_COMMENT_MAX.html","deprecated":false},{"id":"namespace_validation","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VALIDATION.PLAYLIST_TITLE_MAX","file":"shared/validation.ts","doc":"","url":"./shared/validation.ts/~/VALIDATION.PLAYLIST_TITLE_MAX.html","deprecated":false},{"id":"namespace_validation","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VALIDATION.PLAYLIST_DESCRIPTION_MAX","file":"shared/validation.ts","doc":"","url":"./shared/validation.ts/~/VALIDATION.PLAYLIST_DESCRIPTION_MAX.html","deprecated":false},{"id":"namespace_validation","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VALIDATION.COMMENT_BODY_MAX","file":"shared/validation.ts","doc":"","url":"./shared/validation.ts/~/VALIDATION.COMMENT_BODY_MAX.html","deprecated":false},{"id":"namespace_validation","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VALIDATION.USER_DESCRIPTION_MAX","file":"shared/validation.ts","doc":"","url":"./shared/validation.ts/~/VALIDATION.USER_DESCRIPTION_MAX.html","deprecated":false},{"id":"namespace_validation","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VALIDATION.CATEGORY_NAME_MAX","file":"shared/validation.ts","doc":"","url":"./shared/validation.ts/~/VALIDATION.CATEGORY_NAME_MAX.html","deprecated":false},{"id":"namespace_validation","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VALIDATION.CATEGORY_SLUG_MAX","file":"shared/validation.ts","doc":"","url":"./shared/validation.ts/~/VALIDATION.CATEGORY_SLUG_MAX.html","deprecated":false},{"id":"namespace_validation","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VALIDATION.CHAT_MESSAGE_MAX","file":"shared/validation.ts","doc":"","url":"./shared/validation.ts/~/VALIDATION.CHAT_MESSAGE_MAX.html","deprecated":false},{"id":"namespace_username_re","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"USERNAME_RE","file":"shared/validation.ts","doc":"Matches a valid username, made of letters, digits and underscores within the VALIDATION limits. Sign-up and renaming check it on both sides. It uses the same \\w that a handle's pattern (HANDLE_SOURCE) reads a name with; only a user from another instance has the @host part.","url":"./shared/validation.ts/~/USERNAME_RE.html","deprecated":false},{"id":"namespace_host_source","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"HOST_SOURCE","file":"shared/validation.ts","doc":"The pattern of an instance's host as a handle writes it: DNS labels, and a port for instances on one machine (localhost:8001). It ends on a letter or a digit, so the period that ends a sentence after a mention isn't taken in. HANDLE_SOURCE builds on it.","url":"./shared/validation.ts/~/HOST_SOURCE.html","deprecated":false},{"id":"namespace_handle_source","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"HANDLE_SOURCE","file":"shared/validation.ts","doc":"The pattern of a handle, the name a user goes by on this instance: a local user's username, or name@host for a user whose account lives on another gerbeur (federation-service.ts stores it so in users.username). Paths, mentions and the profile links all read names by it, through HANDLE_RE, MENTION_RE (shared/mention.ts) and parsePagePath (shared/paths.ts).","url":"./shared/validation.ts/~/HANDLE_SOURCE.html","deprecated":false},{"id":"namespace_handle_re","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"HANDLE_RE","file":"shared/validation.ts","doc":"Matches a whole handle (HANDLE_SOURCE).","url":"./shared/validation.ts/~/HANDLE_RE.html","deprecated":false},{"id":"namespace_host_re","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"HOST_RE","file":"shared/validation.ts","doc":"Matches a whole host (HOST_SOURCE).","url":"./shared/validation.ts/~/HOST_RE.html","deprecated":false},{"id":"namespace_splithandle","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"splitHandle","file":"shared/validation.ts","doc":"Returns the name and, for a user from another instance, the host of handle. splitHandle(\"alice@music.example\") is { name: \"alice\", host: \"music.example\" }; a local name has no host.","url":"./shared/validation.ts/~/splitHandle.html","deprecated":false},{"id":"namespace_localhandle","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"localHandle","file":"shared/validation.ts","doc":"Returns handle as this instance writes it, isSelfHost telling its own host. Another instance writes a user from here with this one's host, bob@gerbeur.example, who is bob here: a mention or a link copied from there names them so. Any other handle is returned as it is. The server resolves names by it (resolveUsername, the mention notifications), and the chat's highlight (mentionsUser) reads mentions by it.","url":"./shared/validation.ts/~/localHandle.html","deprecated":false},{"id":"namespace_rename_limits","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"RENAME_LIMITS","file":"shared/validation.ts","doc":"How often a dump's or a playlist's slug may change, counted from the aliases the changes left: 3 times a day. Moderators are exempt. slug-service refuses a change past it with a 429, and the edit forms say what the limit is.","url":"./shared/validation.ts/~/RENAME_LIMITS.html","deprecated":false},{"id":"namespace_rename_limits","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RENAME_LIMITS.SLUG","file":"shared/validation.ts","doc":"","url":"./shared/validation.ts/~/RENAME_LIMITS.SLUG.html","deprecated":false},{"id":"namespace_rename_limits","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RENAME_LIMITS.SLUG.count","file":"shared/validation.ts","doc":"","url":"./shared/validation.ts/~/RENAME_LIMITS.SLUG.count.html","deprecated":false},{"id":"namespace_rename_limits","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RENAME_LIMITS.SLUG.windowMs","file":"shared/validation.ts","doc":"","url":"./shared/validation.ts/~/RENAME_LIMITS.SLUG.windowMs.html","deprecated":false},{"id":"namespace_uuid_re","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"UUID_RE","file":"shared/validation.ts","doc":"Matches an id the server makes with crypto.randomUUID(). A route checks one before it names a file on disk, and shared/attachment.ts finds the attachments a text links by it.","url":"./shared/validation.ts/~/UUID_RE.html","deprecated":false},{"id":"namespace_email_re","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"EMAIL_RE","file":"shared/validation.ts","doc":"Matches an email address well enough to catch a typo; only the reset email arriving proves it.","url":"./shared/validation.ts/~/EMAIL_RE.html","deprecated":false},{"id":"namespace_dump_max_file_size_bytes","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"DUMP_MAX_FILE_SIZE_BYTES","file":"shared/validation.ts","doc":"The largest file a file dump may hold, in bytes. dump-service refuses a bigger one, and the create form before uploading it.","url":"./shared/validation.ts/~/DUMP_MAX_FILE_SIZE_BYTES.html","deprecated":false},{"id":"namespace_waveform_peaks","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"WAVEFORM_PEAKS","file":"shared/waveform.ts","doc":"How many peaks, and so bars, a waveform has.","url":"./shared/waveform.ts/~/WAVEFORM_PEAKS.html","deprecated":false},{"id":"namespace_dumpwaveform","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"DumpWaveform","file":"shared/waveform.ts","doc":"Returned by GET /api/dumps/:dumpId/waveform for an audio file dump, to the player's waveform.","url":"./shared/waveform.ts/~/DumpWaveform.html","deprecated":false},{"id":"namespace_dumpwaveform","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpWaveform.peaks","file":"shared/waveform.ts","doc":"WAVEFORM_PEAKS heights from 0 to 1, as peaksOf gives.","url":"./shared/waveform.ts/~/DumpWaveform.peaks.html","deprecated":false},{"id":"namespace_peaksof","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"peaksOf","file":"shared/waveform.ts","doc":"Returns n peaks of samples, each the loudest of its slice, scaled so the loudest of all is 1 and rounded to three places: a quiet recording fills the waveform as a loud one does. samples may be signed, as audio is, or already peaks of smaller slices. Silence gives zeros.","url":"./shared/waveform.ts/~/peaksOf.html","deprecated":false},{"id":"namespace_pingmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PingMessage","file":"shared/ws.ts","doc":"Sent by the server to every socket every 30 s. WSProvider answers PongMessage, and a socket that missed the previous ping is closed. The server also answers a client's ping, though the client never sends one.","url":"./shared/ws.ts/~/PingMessage.html","deprecated":false},{"id":"namespace_pingmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PingMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/PingMessage.type.html","deprecated":false},{"id":"namespace_pongmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PongMessage","file":"shared/ws.ts","doc":"Sent in answer to a PingMessage. The server records the client's to keep its socket open, and the client ignores the server's.","url":"./shared/ws.ts/~/PongMessage.html","deprecated":false},{"id":"namespace_pongmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PongMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/PongMessage.type.html","deprecated":false},{"id":"namespace_votecastmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"VoteCastMessage","file":"shared/ws.ts","doc":"Sent by WSProvider when the user upvotes a dump, after it has shown the vote. The server answers VoteAckMessage, or an ErrorMessage naming the dump, on which the client undoes the vote, as it does when neither comes within 5 s.","url":"./shared/ws.ts/~/VoteCastMessage.html","deprecated":false},{"id":"namespace_votecastmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VoteCastMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/VoteCastMessage.type.html","deprecated":false},{"id":"namespace_votecastmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VoteCastMessage.dumpId","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/VoteCastMessage.dumpId.html","deprecated":false},{"id":"namespace_voteremovemessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"VoteRemoveMessage","file":"shared/ws.ts","doc":"Sent by WSProvider to withdraw an upvote, as VoteCastMessage.","url":"./shared/ws.ts/~/VoteRemoveMessage.html","deprecated":false},{"id":"namespace_voteremovemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VoteRemoveMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/VoteRemoveMessage.type.html","deprecated":false},{"id":"namespace_voteremovemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VoteRemoveMessage.dumpId","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/VoteRemoveMessage.dumpId.html","deprecated":false},{"id":"namespace_commentlikecastmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CommentLikeCastMessage","file":"shared/ws.ts","doc":"Sent by WSProvider when the user likes a comment, and handled as VoteCastMessage is, with CommentLikeAckMessage for the ack.","url":"./shared/ws.ts/~/CommentLikeCastMessage.html","deprecated":false},{"id":"namespace_commentlikecastmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentLikeCastMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/CommentLikeCastMessage.type.html","deprecated":false},{"id":"namespace_commentlikecastmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentLikeCastMessage.commentId","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/CommentLikeCastMessage.commentId.html","deprecated":false},{"id":"namespace_commentlikeremovemessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CommentLikeRemoveMessage","file":"shared/ws.ts","doc":"Sent by WSProvider to withdraw a like, as CommentLikeCastMessage.","url":"./shared/ws.ts/~/CommentLikeRemoveMessage.html","deprecated":false},{"id":"namespace_commentlikeremovemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentLikeRemoveMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/CommentLikeRemoveMessage.type.html","deprecated":false},{"id":"namespace_commentlikeremovemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentLikeRemoveMessage.commentId","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/CommentLikeRemoveMessage.commentId.html","deprecated":false},{"id":"namespace_chatsendmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ChatSendMessage","file":"shared/ws.ts","doc":"Sent by WSProvider when the user posts in the chatbox, which shows the message as pending meanwhile. The server broadcasts it as ChatMessageMessage, or answers a chat ErrorMessage.","url":"./shared/ws.ts/~/ChatSendMessage.html","deprecated":false},{"id":"namespace_chatsendmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatSendMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/ChatSendMessage.type.html","deprecated":false},{"id":"namespace_chatsendmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatSendMessage.body","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/ChatSendMessage.body.html","deprecated":false},{"id":"namespace_chatsendmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatSendMessage.replyToId","file":"shared/ws.ts","doc":"Ignored if longer than 64 characters or naming no message.","url":"./shared/ws.ts/~/ChatSendMessage.replyToId.html","deprecated":false},{"id":"namespace_chatsendmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatSendMessage.nonce","file":"shared/ws.ts","doc":"Chosen by the client, and echoed on the broadcast or the error, so that it can match the outcome to its pending message. Ignored if longer than 64 characters.","url":"./shared/ws.ts/~/ChatSendMessage.nonce.html","deprecated":false},{"id":"namespace_chattypingmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ChatTypingMessage","file":"shared/ws.ts","doc":"Sent by the chatbox while the user types, every 3 s, and once they pause. The server answers every signed-in socket with ChatTypingUpdateMessage when the user starts or stops, and forgets a typer it hasn't heard from in 6 s.","url":"./shared/ws.ts/~/ChatTypingMessage.html","deprecated":false},{"id":"namespace_chattypingmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatTypingMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/ChatTypingMessage.type.html","deprecated":false},{"id":"namespace_chattypingmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatTypingMessage.typing","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/ChatTypingMessage.typing.html","deprecated":false},{"id":"namespace_chatfocusmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ChatFocusMessage","file":"shared/ws.ts","doc":"Sent by WSProvider when the chatbox opens or closes, when the tab is hidden or shown, and after each welcome. The server notifies no one of a chat mention while one of their sockets says open.","url":"./shared/ws.ts/~/ChatFocusMessage.html","deprecated":false},{"id":"namespace_chatfocusmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatFocusMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/ChatFocusMessage.type.html","deprecated":false},{"id":"namespace_chatfocusmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatFocusMessage.open","file":"shared/ws.ts","doc":"True only while the chatbox is open in a visible tab.","url":"./shared/ws.ts/~/ChatFocusMessage.open.html","deprecated":false},{"id":"namespace_chateditmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ChatEditMessage","file":"shared/ws.ts","doc":"Sent by WSProvider when the user edits a chat message, their own or, with chat:moderate, anyone's. The server broadcasts ChatMessageUpdatedMessage, or answers a chat ErrorMessage.","url":"./shared/ws.ts/~/ChatEditMessage.html","deprecated":false},{"id":"namespace_chateditmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatEditMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/ChatEditMessage.type.html","deprecated":false},{"id":"namespace_chateditmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatEditMessage.id","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/ChatEditMessage.id.html","deprecated":false},{"id":"namespace_chateditmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatEditMessage.body","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/ChatEditMessage.body.html","deprecated":false},{"id":"namespace_chatdeletemessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ChatDeleteMessage","file":"shared/ws.ts","doc":"Sent by WSProvider when the user deletes a chat message, as ChatEditMessage. The server broadcasts ChatMessageDeletedMessage.","url":"./shared/ws.ts/~/ChatDeleteMessage.html","deprecated":false},{"id":"namespace_chatdeletemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatDeleteMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/ChatDeleteMessage.type.html","deprecated":false},{"id":"namespace_chatdeletemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatDeleteMessage.id","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/ChatDeleteMessage.id.html","deprecated":false},{"id":"namespace_chatreadmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ChatReadMessage","file":"shared/ws.ts","doc":"Sent by WSProvider, at most once a second, as the user reads the chat. The server moves their read marker to at, a message's ISO createdAt, and answers ChatReadUpdateMessage. It drops the message silently when it is malformed or over its rate limit.","url":"./shared/ws.ts/~/ChatReadMessage.html","deprecated":false},{"id":"namespace_chatreadmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatReadMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/ChatReadMessage.type.html","deprecated":false},{"id":"namespace_chatreadmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatReadMessage.at","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/ChatReadMessage.at.html","deprecated":false},{"id":"namespace_clienttoservermessage","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"ClientToServerMessage","file":"shared/ws.ts","doc":"Sent by WSProvider, and dispatched by the route's handleMessage, which checks each field's type before using it.","url":"./shared/ws.ts/~/ClientToServerMessage.html","deprecated":false},{"id":"namespace_onlineuser","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"OnlineUser","file":"shared/ws.ts","doc":"Sent by the server in WelcomeMessage, PresenceUpdateMessage and ChatTypingUpdateMessage, once per signed-in user whatever their number of sockets.","url":"./shared/ws.ts/~/OnlineUser.html","deprecated":false},{"id":"namespace_onlineuser","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"OnlineUser.userId","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/OnlineUser.userId.html","deprecated":false},{"id":"namespace_onlineuser","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"OnlineUser.username","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/OnlineUser.username.html","deprecated":false},{"id":"namespace_onlineuser","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"OnlineUser.hasAvatar","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/OnlineUser.hasAvatar.html","deprecated":false},{"id":"namespace_onlineuser","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"OnlineUser.avatarVersion","file":"shared/ws.ts","doc":"Set when the avatar changed while the user was connected, for the client to append to the avatar's URL so it doesn't show the cached one.","url":"./shared/ws.ts/~/OnlineUser.avatarVersion.html","deprecated":false},{"id":"namespace_welcomemessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"WelcomeMessage","file":"shared/ws.ts","doc":"Sent by the server to a socket once it opens, just after the PresenceUpdateMessage that announces it. WSProvider replaces its state with this one, dropping its pending votes and likes. After a reconnect, it also bumps connectionEpoch, so that pages refetch what they missed. The per-user fields are empty or zero on an anonymous socket.","url":"./shared/ws.ts/~/WelcomeMessage.html","deprecated":false},{"id":"namespace_welcomemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WelcomeMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/WelcomeMessage.type.html","deprecated":false},{"id":"namespace_welcomemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WelcomeMessage.users","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/WelcomeMessage.users.html","deprecated":false},{"id":"namespace_welcomemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WelcomeMessage.myVotes","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/WelcomeMessage.myVotes.html","deprecated":false},{"id":"namespace_welcomemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WelcomeMessage.myCommentLikes","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/WelcomeMessage.myCommentLikes.html","deprecated":false},{"id":"namespace_welcomemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WelcomeMessage.unreadNotificationCount","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/WelcomeMessage.unreadNotificationCount.html","deprecated":false},{"id":"namespace_welcomemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WelcomeMessage.chatReadAt","file":"shared/ws.ts","doc":"Absent on an anonymous socket.","url":"./shared/ws.ts/~/WelcomeMessage.chatReadAt.html","deprecated":false},{"id":"namespace_welcomemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WelcomeMessage.unreadChatCount","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/WelcomeMessage.unreadChatCount.html","deprecated":false},{"id":"namespace_presenceupdatemessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PresenceUpdateMessage","file":"shared/ws.ts","doc":"Sent by the server to every socket when a socket opens or closes, and when a connected user's avatar changes.","url":"./shared/ws.ts/~/PresenceUpdateMessage.html","deprecated":false},{"id":"namespace_presenceupdatemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PresenceUpdateMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/PresenceUpdateMessage.type.html","deprecated":false},{"id":"namespace_presenceupdatemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PresenceUpdateMessage.users","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/PresenceUpdateMessage.users.html","deprecated":false},{"id":"namespace_votesupdatemessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"VotesUpdateMessage","file":"shared/ws.ts","doc":"Sent by the server after a vote, to every socket, or to the poster's alone for a private dump. WSProvider updates the count, and when voterId is the user, it updates their votes too, so their other tabs follow.","url":"./shared/ws.ts/~/VotesUpdateMessage.html","deprecated":false},{"id":"namespace_votesupdatemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VotesUpdateMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/VotesUpdateMessage.type.html","deprecated":false},{"id":"namespace_votesupdatemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VotesUpdateMessage.dumpId","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/VotesUpdateMessage.dumpId.html","deprecated":false},{"id":"namespace_votesupdatemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VotesUpdateMessage.voteCount","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/VotesUpdateMessage.voteCount.html","deprecated":false},{"id":"namespace_votesupdatemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VotesUpdateMessage.voterId","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/VotesUpdateMessage.voterId.html","deprecated":false},{"id":"namespace_votesupdatemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VotesUpdateMessage.action","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/VotesUpdateMessage.action.html","deprecated":false},{"id":"namespace_voteackmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"VoteAckMessage","file":"shared/ws.ts","doc":"Sent by the server to the socket that sent a VoteCastMessage or VoteRemoveMessage, once the vote is stored. WSProvider confirms its optimistic vote with it.","url":"./shared/ws.ts/~/VoteAckMessage.html","deprecated":false},{"id":"namespace_voteackmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VoteAckMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/VoteAckMessage.type.html","deprecated":false},{"id":"namespace_voteackmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VoteAckMessage.dumpId","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/VoteAckMessage.dumpId.html","deprecated":false},{"id":"namespace_voteackmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VoteAckMessage.action","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/VoteAckMessage.action.html","deprecated":false},{"id":"namespace_voteackmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VoteAckMessage.voteCount","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/VoteAckMessage.voteCount.html","deprecated":false},{"id":"namespace_commentlikesupdatemessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CommentLikesUpdateMessage","file":"shared/ws.ts","doc":"Sent by the server after a like, as VotesUpdateMessage is after a vote: to the dump's poster alone when the comment is on a private dump.","url":"./shared/ws.ts/~/CommentLikesUpdateMessage.html","deprecated":false},{"id":"namespace_commentlikesupdatemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentLikesUpdateMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/CommentLikesUpdateMessage.type.html","deprecated":false},{"id":"namespace_commentlikesupdatemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentLikesUpdateMessage.commentId","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/CommentLikesUpdateMessage.commentId.html","deprecated":false},{"id":"namespace_commentlikesupdatemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentLikesUpdateMessage.likeCount","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/CommentLikesUpdateMessage.likeCount.html","deprecated":false},{"id":"namespace_commentlikesupdatemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentLikesUpdateMessage.likerId","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/CommentLikesUpdateMessage.likerId.html","deprecated":false},{"id":"namespace_commentlikesupdatemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentLikesUpdateMessage.action","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/CommentLikesUpdateMessage.action.html","deprecated":false},{"id":"namespace_commentlikeackmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CommentLikeAckMessage","file":"shared/ws.ts","doc":"Sent by the server to the socket that liked or unliked a comment, as VoteAckMessage is for a vote.","url":"./shared/ws.ts/~/CommentLikeAckMessage.html","deprecated":false},{"id":"namespace_commentlikeackmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentLikeAckMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/CommentLikeAckMessage.type.html","deprecated":false},{"id":"namespace_commentlikeackmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentLikeAckMessage.commentId","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/CommentLikeAckMessage.commentId.html","deprecated":false},{"id":"namespace_commentlikeackmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentLikeAckMessage.action","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/CommentLikeAckMessage.action.html","deprecated":false},{"id":"namespace_commentlikeackmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentLikeAckMessage.likeCount","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/CommentLikeAckMessage.likeCount.html","deprecated":false},{"id":"namespace_dumpcreatedmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"DumpCreatedMessage","file":"shared/ws.ts","doc":"Sent by the server when a dump is posted, to every socket if it is public and to its poster's alone if it is private. It also goes to everyone but the poster when a private dump goes public, since to them it is new. WSProvider puts it at the top of its recent dumps.","url":"./shared/ws.ts/~/DumpCreatedMessage.html","deprecated":false},{"id":"namespace_dumpcreatedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpCreatedMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/DumpCreatedMessage.type.html","deprecated":false},{"id":"namespace_dumpcreatedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpCreatedMessage.dump","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/DumpCreatedMessage.dump.html","deprecated":false},{"id":"namespace_dumpupdatedmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"DumpUpdatedMessage","file":"shared/ws.ts","doc":"Sent by the server when a dump changes, to every socket if it is public and to its poster's alone if it is private, as when it has just gone private. WSProvider refreshes it in place, without moving it up the feeds.","url":"./shared/ws.ts/~/DumpUpdatedMessage.html","deprecated":false},{"id":"namespace_dumpupdatedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpUpdatedMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/DumpUpdatedMessage.type.html","deprecated":false},{"id":"namespace_dumpupdatedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpUpdatedMessage.dump","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/DumpUpdatedMessage.dump.html","deprecated":false},{"id":"namespace_dumpdeletedmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"DumpDeletedMessage","file":"shared/ws.ts","doc":"Sent by the server when a dump is deleted, to every socket if it was public and to its poster's alone if it was private. It also goes to everyone but the poster when a public dump goes private. WSProvider drops it from every list.","url":"./shared/ws.ts/~/DumpDeletedMessage.html","deprecated":false},{"id":"namespace_dumpdeletedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpDeletedMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/DumpDeletedMessage.type.html","deprecated":false},{"id":"namespace_dumpdeletedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpDeletedMessage.dumpId","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/DumpDeletedMessage.dumpId.html","deprecated":false},{"id":"namespace_dumprelatedchangedmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"DumpRelatedChangedMessage","file":"shared/ws.ts","doc":"Sent by the server when the dumps related to some dumps changed: a note or a comment gained or lost a link to a dump, or a dump that has such links turned public. It goes to the sockets whose user may see both ends of a link. The Dump page showing one of dumpIds fetches its related dumps again.","url":"./shared/ws.ts/~/DumpRelatedChangedMessage.html","deprecated":false},{"id":"namespace_dumprelatedchangedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpRelatedChangedMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/DumpRelatedChangedMessage.type.html","deprecated":false},{"id":"namespace_dumprelatedchangedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpRelatedChangedMessage.dumpIds","file":"shared/ws.ts","doc":"The dump whose links changed, then the dumps at their other end, without those this socket's user may not see.","url":"./shared/ws.ts/~/DumpRelatedChangedMessage.dumpIds.html","deprecated":false},{"id":"namespace_playlistcreatedmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PlaylistCreatedMessage","file":"shared/ws.ts","doc":"Sent by the server when a playlist is created, to every socket if it is public, else to its owner's. It also goes to everyone but the owner when a private playlist goes public, since to them it is new. WSProvider passes it on to the playlist pages as a playlist event, as it does the three messages below.","url":"./shared/ws.ts/~/PlaylistCreatedMessage.html","deprecated":false},{"id":"namespace_playlistcreatedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistCreatedMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/PlaylistCreatedMessage.type.html","deprecated":false},{"id":"namespace_playlistcreatedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistCreatedMessage.playlist","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/PlaylistCreatedMessage.playlist.html","deprecated":false},{"id":"namespace_playlistupdatedmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PlaylistUpdatedMessage","file":"shared/ws.ts","doc":"Sent by the server when a playlist changes, to every socket if it is public, else to its owner's, as when it has just gone private. Its dumpCount and lastDumpAt are the socket's user's, as in playlist_created.","url":"./shared/ws.ts/~/PlaylistUpdatedMessage.html","deprecated":false},{"id":"namespace_playlistupdatedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistUpdatedMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/PlaylistUpdatedMessage.type.html","deprecated":false},{"id":"namespace_playlistupdatedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistUpdatedMessage.playlist","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/PlaylistUpdatedMessage.playlist.html","deprecated":false},{"id":"namespace_playlistdeletedmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PlaylistDeletedMessage","file":"shared/ws.ts","doc":"Sent by the server when a playlist is deleted, to those who could see it. It also goes to everyone but the owner when a public playlist goes private.","url":"./shared/ws.ts/~/PlaylistDeletedMessage.html","deprecated":false},{"id":"namespace_playlistdeletedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistDeletedMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/PlaylistDeletedMessage.type.html","deprecated":false},{"id":"namespace_playlistdeletedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistDeletedMessage.playlistId","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/PlaylistDeletedMessage.playlistId.html","deprecated":false},{"id":"namespace_playlistdeletedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistDeletedMessage.userId","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/PlaylistDeletedMessage.userId.html","deprecated":false},{"id":"namespace_playlistdumpsupdatedmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PlaylistDumpsUpdatedMessage","file":"shared/ws.ts","doc":"Sent by the server when dumps are added to, removed from or reordered in a playlist, to those who can see it, and when one of its dumps is deleted or changes visibility, which changes what its viewers see of it.","url":"./shared/ws.ts/~/PlaylistDumpsUpdatedMessage.html","deprecated":false},{"id":"namespace_playlistdumpsupdatedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistDumpsUpdatedMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/PlaylistDumpsUpdatedMessage.type.html","deprecated":false},{"id":"namespace_playlistdumpsupdatedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistDumpsUpdatedMessage.playlistId","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/PlaylistDumpsUpdatedMessage.playlistId.html","deprecated":false},{"id":"namespace_playlistdumpsupdatedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistDumpsUpdatedMessage.dumpIds","file":"shared/ws.ts","doc":"Only the dumps this socket's user may see, in order: another user's private dump is left out.","url":"./shared/ws.ts/~/PlaylistDumpsUpdatedMessage.dumpIds.html","deprecated":false},{"id":"namespace_playlistdumpsupdatedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistDumpsUpdatedMessage.lastDumpAt","file":"shared/ws.ts","doc":"When the latest of them was added, the playlist's lastDumpAt for this socket's user. It is missing when dumpIds is empty.","url":"./shared/ws.ts/~/PlaylistDumpsUpdatedMessage.lastDumpAt.html","deprecated":false},{"id":"namespace_userupdatedmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UserUpdatedMessage","file":"shared/ws.ts","doc":"Sent by the server to every socket after a profile edit, a rename, a role change or an avatar upload. WSProvider refreshes the user's avatar wherever it shows, and passes it on as a user event, which updates their profile and their name on the lists.","url":"./shared/ws.ts/~/UserUpdatedMessage.html","deprecated":false},{"id":"namespace_userupdatedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserUpdatedMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/UserUpdatedMessage.type.html","deprecated":false},{"id":"namespace_userupdatedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserUpdatedMessage.user","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/UserUpdatedMessage.user.html","deprecated":false},{"id":"namespace_commentcreatedmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CommentCreatedMessage","file":"shared/ws.ts","doc":"Sent by the server when a comment is posted, to every socket if its dump is public, else to the dump's poster's. WSProvider passes it on to the dump's page and the dump lists as a comment event, as it does the two messages below.","url":"./shared/ws.ts/~/CommentCreatedMessage.html","deprecated":false},{"id":"namespace_commentcreatedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentCreatedMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/CommentCreatedMessage.type.html","deprecated":false},{"id":"namespace_commentcreatedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentCreatedMessage.comment","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/CommentCreatedMessage.comment.html","deprecated":false},{"id":"namespace_commentupdatedmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CommentUpdatedMessage","file":"shared/ws.ts","doc":"Sent by the server when a comment is edited, as when one is posted.","url":"./shared/ws.ts/~/CommentUpdatedMessage.html","deprecated":false},{"id":"namespace_commentupdatedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentUpdatedMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/CommentUpdatedMessage.type.html","deprecated":false},{"id":"namespace_commentupdatedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentUpdatedMessage.comment","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/CommentUpdatedMessage.comment.html","deprecated":false},{"id":"namespace_commentdeletedmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CommentDeletedMessage","file":"shared/ws.ts","doc":"Sent by the server when a comment is deleted, as when one is posted.","url":"./shared/ws.ts/~/CommentDeletedMessage.html","deprecated":false},{"id":"namespace_commentdeletedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentDeletedMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/CommentDeletedMessage.type.html","deprecated":false},{"id":"namespace_commentdeletedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentDeletedMessage.commentId","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/CommentDeletedMessage.commentId.html","deprecated":false},{"id":"namespace_commentdeletedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentDeletedMessage.dumpId","file":"shared/ws.ts","doc":"Lets a dump's page ignore the comments of other dumps.","url":"./shared/ws.ts/~/CommentDeletedMessage.dumpId.html","deprecated":false},{"id":"namespace_notificationcreatedmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"NotificationCreatedMessage","file":"shared/ws.ts","doc":"Sent by the notification service to every socket of the notified user. WSProvider bumps the unread count and chimes.","url":"./shared/ws.ts/~/NotificationCreatedMessage.html","deprecated":false},{"id":"namespace_notificationcreatedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"NotificationCreatedMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/NotificationCreatedMessage.type.html","deprecated":false},{"id":"namespace_notificationcreatedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"NotificationCreatedMessage.notification","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/NotificationCreatedMessage.notification.html","deprecated":false},{"id":"namespace_notificationsreadmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"NotificationsReadMessage","file":"shared/ws.ts","doc":"Sent by the notification service to every socket of a user who opened their notifications, which marks them all read. WSProvider zeroes the bell's count, in the other tabs and devices too.","url":"./shared/ws.ts/~/NotificationsReadMessage.html","deprecated":false},{"id":"namespace_notificationsreadmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"NotificationsReadMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/NotificationsReadMessage.type.html","deprecated":false},{"id":"namespace_categorieschangedmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CategoriesChangedMessage","file":"shared/ws.ts","doc":"Sent by the category service to every socket after a category is created, edited or deleted. CategoriesProvider fetches the categories again.","url":"./shared/ws.ts/~/CategoriesChangedMessage.html","deprecated":false},{"id":"namespace_categorieschangedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CategoriesChangedMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/CategoriesChangedMessage.type.html","deprecated":false},{"id":"namespace_errormessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ErrorMessage","file":"shared/ws.ts","doc":"Sent by the server to the socket whose message failed. With dumpId or commentId, WSProvider undoes that optimistic vote or like at once rather than after its 5 s timeout. With scope, the chatbox shows it, on the pending message nonce names or as a notice. Any other error is ignored.","url":"./shared/ws.ts/~/ErrorMessage.html","deprecated":false},{"id":"namespace_errormessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ErrorMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/ErrorMessage.type.html","deprecated":false},{"id":"namespace_errormessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ErrorMessage.message","file":"shared/ws.ts","doc":"In English: the chatbox shows it untranslated.","url":"./shared/ws.ts/~/ErrorMessage.message.html","deprecated":false},{"id":"namespace_errormessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ErrorMessage.dumpId","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/ErrorMessage.dumpId.html","deprecated":false},{"id":"namespace_errormessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ErrorMessage.commentId","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/ErrorMessage.commentId.html","deprecated":false},{"id":"namespace_errormessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ErrorMessage.action","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/ErrorMessage.action.html","deprecated":false},{"id":"namespace_errormessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ErrorMessage.scope","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/ErrorMessage.scope.html","deprecated":false},{"id":"namespace_errormessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ErrorMessage.nonce","file":"shared/ws.ts","doc":"Set only on the failure of a ChatSendMessage that had one.","url":"./shared/ws.ts/~/ErrorMessage.nonce.html","deprecated":false},{"id":"namespace_chatmessagemessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ChatMessageMessage","file":"shared/ws.ts","doc":"Sent by the server to every signed-in socket, the sender's included, when a chat message is posted. WSProvider adds it to the live chat, counts it unread unless the user is reading the chat, and may chime.","url":"./shared/ws.ts/~/ChatMessageMessage.html","deprecated":false},{"id":"namespace_chatmessagemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/ChatMessageMessage.type.html","deprecated":false},{"id":"namespace_chatmessagemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageMessage.message","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/ChatMessageMessage.message.html","deprecated":false},{"id":"namespace_chatmessagemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageMessage.nonce","file":"shared/ws.ts","doc":"The sender's ChatSendMessage nonce, by which its client swaps the pending copy for this one.","url":"./shared/ws.ts/~/ChatMessageMessage.nonce.html","deprecated":false},{"id":"namespace_chatmessageupdatedmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ChatMessageUpdatedMessage","file":"shared/ws.ts","doc":"Sent by the server to every signed-in socket when a chat message is edited.","url":"./shared/ws.ts/~/ChatMessageUpdatedMessage.html","deprecated":false},{"id":"namespace_chatmessageupdatedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageUpdatedMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/ChatMessageUpdatedMessage.type.html","deprecated":false},{"id":"namespace_chatmessageupdatedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageUpdatedMessage.message","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/ChatMessageUpdatedMessage.message.html","deprecated":false},{"id":"namespace_chatmessagedeletedmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ChatMessageDeletedMessage","file":"shared/ws.ts","doc":"Sent by the server to every signed-in socket when a chat message is deleted. The client also keeps the id, to show the replies to it as replies to a deleted message.","url":"./shared/ws.ts/~/ChatMessageDeletedMessage.html","deprecated":false},{"id":"namespace_chatmessagedeletedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageDeletedMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/ChatMessageDeletedMessage.type.html","deprecated":false},{"id":"namespace_chatmessagedeletedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageDeletedMessage.id","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/ChatMessageDeletedMessage.id.html","deprecated":false},{"id":"namespace_chattypingupdatemessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ChatTypingUpdateMessage","file":"shared/ws.ts","doc":"Sent by the server to every signed-in socket when a user starts or stops typing in the chat, with everyone typing. The chatbox shows their avatars.","url":"./shared/ws.ts/~/ChatTypingUpdateMessage.html","deprecated":false},{"id":"namespace_chattypingupdatemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatTypingUpdateMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/ChatTypingUpdateMessage.type.html","deprecated":false},{"id":"namespace_chattypingupdatemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatTypingUpdateMessage.users","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/ChatTypingUpdateMessage.users.html","deprecated":false},{"id":"namespace_chatreadupdatemessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ChatReadUpdateMessage","file":"shared/ws.ts","doc":"Sent by the server to every socket of a user after their ChatReadMessage, so that all their tabs and devices update the chat's badge.","url":"./shared/ws.ts/~/ChatReadUpdateMessage.html","deprecated":false},{"id":"namespace_chatreadupdatemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatReadUpdateMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/ChatReadUpdateMessage.type.html","deprecated":false},{"id":"namespace_chatreadupdatemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatReadUpdateMessage.readAt","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/ChatReadUpdateMessage.readAt.html","deprecated":false},{"id":"namespace_chatreadupdatemessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatReadUpdateMessage.unread","file":"shared/ws.ts","doc":"Counts only the messages of other users after readAt.","url":"./shared/ws.ts/~/ChatReadUpdateMessage.unread.html","deprecated":false},{"id":"namespace_followschangedmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"FollowsChangedMessage","file":"shared/ws.ts","doc":"Sent by the server to every socket of a user who followed or unfollowed a user or a playlist, so that FollowProvider in their other tabs refetches the follow status.","url":"./shared/ws.ts/~/FollowsChangedMessage.html","deprecated":false},{"id":"namespace_followschangedmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FollowsChangedMessage.type","file":"shared/ws.ts","doc":"","url":"./shared/ws.ts/~/FollowsChangedMessage.type.html","deprecated":false},{"id":"namespace_servertoclientmessage","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"ServerToClientMessage","file":"shared/ws.ts","doc":"Sent by services/ws-service.ts and the WebSocket route, and handled by WSProvider's onmessage.","url":"./shared/ws.ts/~/ServerToClientMessage.html","deprecated":false},{"id":"namespace_approutes","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"AppRoutes","file":"src/App.tsx","doc":"Renders the route table, and the floating buttons over every page. Exported for the tests, which reach a page through it as a visit does.","url":"./src/App.tsx/~/AppRoutes.html","deprecated":false},{"id":"namespace_app","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"App","file":"src/App.tsx","doc":"Renders the app. The theme, player, socket, follow and chat providers read the session, and ChatProvider reads the URL, so it sits inside the router. GlobalPlayer sits outside the routes, so playback survives navigation.","url":"./src/App.tsx/~/App.html","deprecated":false},{"id":"namespace_categorychipsprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CategoryChipsProps","file":"src/components/category/CategoryChips.tsx","doc":"Passed to CategoryChips by DumpCard and Dump for a dump, and by PlaylistCard and PlaylistHeader for a playlist.","url":"./src/components/category/CategoryChips.tsx/~/CategoryChipsProps.html","deprecated":false},{"id":"namespace_categorychipsprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CategoryChipsProps.kind","file":"src/components/category/CategoryChips.tsx","doc":"Whether ids name dump or playlist categories.","url":"./src/components/category/CategoryChips.tsx/~/CategoryChipsProps.kind.html","deprecated":false},{"id":"namespace_categorychipsprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CategoryChipsProps.ids","file":"src/components/category/CategoryChips.tsx","doc":"The dump's or playlist's categoryIds.","url":"./src/components/category/CategoryChips.tsx/~/CategoryChipsProps.ids.html","deprecated":false},{"id":"namespace_categorychipsprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CategoryChipsProps.className","file":"src/components/category/CategoryChips.tsx","doc":"Added to the row's own class, for a card's grid to place it.","url":"./src/components/category/CategoryChips.tsx/~/CategoryChipsProps.className.html","deprecated":false},{"id":"namespace_categorychipsprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CategoryChipsProps.onClick","file":"src/components/category/CategoryChips.tsx","doc":"Called on a click in the row. A clickable card stops it there, or a chip's click would open the card too.","url":"./src/components/category/CategoryChips.tsx/~/CategoryChipsProps.onClick.html","deprecated":false},{"id":"namespace_categorychips","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"CategoryChips","file":"src/components/category/CategoryChips.tsx","doc":"Renders each category ids names as a chip linking to its page, a dump category's feed or a playlist category's playlists, in the categories' order. Ids of categories since deleted are skipped, and it renders nothing when none is left.","url":"./src/components/category/CategoryChips.tsx/~/CategoryChips.html","deprecated":false},{"id":"namespace_categorymanagerprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CategoryManagerProps","file":"src/components/category/CategoryManager.tsx","doc":"Passed to CategoryManager by Manage, once for each kind.","url":"./src/components/category/CategoryManager.tsx/~/CategoryManagerProps.html","deprecated":false},{"id":"namespace_categorymanagerprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CategoryManagerProps.kind","file":"src/components/category/CategoryManager.tsx","doc":"The set it edits, and the kind of the categories it creates.","url":"./src/components/category/CategoryManager.tsx/~/CategoryManagerProps.kind.html","deprecated":false},{"id":"namespace_categorymanager","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"CategoryManager","file":"src/components/category/CategoryManager.tsx","doc":"Renders the categories of kind as chips that open an inline editor, and a \"+\" chip that creates one. Only one editor is open at a time. A change refetches the app-wide list, so the category switchers follow. Manage shows it only to those who hold category:manage, and the server checks it again.","url":"./src/components/category/CategoryManager.tsx/~/CategoryManager.html","deprecated":false},{"id":"namespace_categoryselectprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CategorySelectProps","file":"src/components/category/CategorySelect.tsx","doc":"Passed to CategorySelect by DumpCreateModal and DumpEdit, and by PlaylistCreateForm and PlaylistEditForm, which hold the selection and send it as the dump's or playlist's categoryIds.","url":"./src/components/category/CategorySelect.tsx/~/CategorySelectProps.html","deprecated":false},{"id":"namespace_categoryselectprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CategorySelectProps.kind","file":"src/components/category/CategorySelect.tsx","doc":"The set it offers: dump categories for a dump, playlist ones for a playlist.","url":"./src/components/category/CategorySelect.tsx/~/CategorySelectProps.kind.html","deprecated":false},{"id":"namespace_categoryselectprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CategorySelectProps.selected","file":"src/components/category/CategorySelect.tsx","doc":"","url":"./src/components/category/CategorySelect.tsx/~/CategorySelectProps.selected.html","deprecated":false},{"id":"namespace_categoryselectprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CategorySelectProps.onToggle","file":"src/components/category/CategorySelect.tsx","doc":"","url":"./src/components/category/CategorySelect.tsx/~/CategorySelectProps.onToggle.html","deprecated":false},{"id":"namespace_categoryselectprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CategorySelectProps.disabled","file":"src/components/category/CategorySelect.tsx","doc":"","url":"./src/components/category/CategorySelect.tsx/~/CategorySelectProps.disabled.html","deprecated":false},{"id":"namespace_categoryselect","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"CategorySelect","file":"src/components/category/CategorySelect.tsx","doc":"Renders the categories of kind as toggle chips, any number of which may be on. It renders nothing while the site has none.","url":"./src/components/category/CategorySelect.tsx/~/CategorySelect.html","deprecated":false},{"id":"namespace_categoryswitcherprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CategorySwitcherProps","file":"src/components/category/CategorySwitcher.tsx","doc":"Passed to CategorySwitcher by FeedTabBar, ProfileDumpsTab, ProfilePlaylistsTab, Playlists and Search, which keep the category in their URL.","url":"./src/components/category/CategorySwitcher.tsx/~/CategorySwitcherProps.html","deprecated":false},{"id":"namespace_categoryswitcherprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CategorySwitcherProps.kind","file":"src/components/category/CategorySwitcher.tsx","doc":"The set it offers: dump categories for dumps, playlist ones for playlists.","url":"./src/components/category/CategorySwitcher.tsx/~/CategorySwitcherProps.kind.html","deprecated":false},{"id":"namespace_categoryswitcherprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CategorySwitcherProps.categorySlug","file":"src/components/category/CategorySwitcher.tsx","doc":"The category shown, or none for every dump or playlist.","url":"./src/components/category/CategorySwitcher.tsx/~/CategorySwitcherProps.categorySlug.html","deprecated":false},{"id":"namespace_categoryswitcherprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CategorySwitcherProps.onSelect","file":"src/components/category/CategorySwitcher.tsx","doc":"Called with the slug of the category picked, or undefined for \"All\".","url":"./src/components/category/CategorySwitcher.tsx/~/CategorySwitcherProps.onSelect.html","deprecated":false},{"id":"namespace_categoryswitcher","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"CategorySwitcher","file":"src/components/category/CategorySwitcher.tsx","doc":"Renders a button naming the category shown, \"All\" without one, that opens the menu of every category of kind. It renders nothing while the site has none.","url":"./src/components/category/CategorySwitcher.tsx/~/CategorySwitcher.html","deprecated":false},{"id":"namespace_chateditboxprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ChatEditBoxProps","file":"src/components/chat/ChatEditBox.tsx","doc":"Passed to ChatEditBox by ChatMessageItem while it is editing.","url":"./src/components/chat/ChatEditBox.tsx/~/ChatEditBoxProps.html","deprecated":false},{"id":"namespace_chateditboxprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatEditBoxProps.initial","file":"src/components/chat/ChatEditBox.tsx","doc":"","url":"./src/components/chat/ChatEditBox.tsx/~/ChatEditBoxProps.initial.html","deprecated":false},{"id":"namespace_chateditboxprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatEditBoxProps.onSave","file":"src/components/chat/ChatEditBox.tsx","doc":"Receives the trimmed text, only when it changed and can be sent.","url":"./src/components/chat/ChatEditBox.tsx/~/ChatEditBoxProps.onSave.html","deprecated":false},{"id":"namespace_chateditboxprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatEditBoxProps.onClose","file":"src/components/chat/ChatEditBox.tsx","doc":"Called once the text is saved, or left, Escape included.","url":"./src/components/chat/ChatEditBox.tsx/~/ChatEditBoxProps.onClose.html","deprecated":false},{"id":"namespace_chateditbox","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"ChatEditBox","file":"src/components/chat/ChatEditBox.tsx","doc":"Renders the field every text edited in place gets, InlineEditField, with Enter saving and Shift+Enter starting a new line, as in the composer. It scrolls itself into the list's view.","url":"./src/components/chat/ChatEditBox.tsx/~/ChatEditBox.html","deprecated":false},{"id":"namespace_chatmessageitemprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ChatMessageItemProps","file":"src/components/chat/ChatMessageItem.tsx","doc":"Passed to ChatMessageItem by ChatModal for each message row. The modal holds the edit, flash and permission state, and sends the edits and deletions over the socket.","url":"./src/components/chat/ChatMessageItem.tsx/~/ChatMessageItemProps.html","deprecated":false},{"id":"namespace_chatmessageitemprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageItemProps.message","file":"src/components/chat/ChatMessageItem.tsx","doc":"","url":"./src/components/chat/ChatMessageItem.tsx/~/ChatMessageItemProps.message.html","deprecated":false},{"id":"namespace_chatmessageitemprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageItemProps.grouped","file":"src/components/chat/ChatMessageItem.tsx","doc":"Set when the message continues its author's run. It then has no avatar or author line: its time shows in the avatar's place on hover, and its actions float over its top.","url":"./src/components/chat/ChatMessageItem.tsx/~/ChatMessageItemProps.grouped.html","deprecated":false},{"id":"namespace_chatmessageitemprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageItemProps.mentionsMe","file":"src/components/chat/ChatMessageItem.tsx","doc":"Highlights a message that @mentions the user, @everyone included, or replies to them.","url":"./src/components/chat/ChatMessageItem.tsx/~/ChatMessageItemProps.mentionsMe.html","deprecated":false},{"id":"namespace_chatmessageitemprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageItemProps.replyDeleted","file":"src/components/chat/ChatMessageItem.tsx","doc":"Set when the replied-to message was deleted live, after the server filled in replyToAuthor.","url":"./src/components/chat/ChatMessageItem.tsx/~/ChatMessageItemProps.replyDeleted.html","deprecated":false},{"id":"namespace_chatmessageitemprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageItemProps.canEdit","file":"src/components/chat/ChatMessageItem.tsx","doc":"","url":"./src/components/chat/ChatMessageItem.tsx/~/ChatMessageItemProps.canEdit.html","deprecated":false},{"id":"namespace_chatmessageitemprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageItemProps.canDelete","file":"src/components/chat/ChatMessageItem.tsx","doc":"","url":"./src/components/chat/ChatMessageItem.tsx/~/ChatMessageItemProps.canDelete.html","deprecated":false},{"id":"namespace_chatmessageitemprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageItemProps.flashed","file":"src/components/chat/ChatMessageItem.tsx","doc":"","url":"./src/components/chat/ChatMessageItem.tsx/~/ChatMessageItemProps.flashed.html","deprecated":false},{"id":"namespace_chatmessageitemprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageItemProps.editing","file":"src/components/chat/ChatMessageItem.tsx","doc":"","url":"./src/components/chat/ChatMessageItem.tsx/~/ChatMessageItemProps.editing.html","deprecated":false},{"id":"namespace_chatmessageitemprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageItemProps.onStartEdit","file":"src/components/chat/ChatMessageItem.tsx","doc":"","url":"./src/components/chat/ChatMessageItem.tsx/~/ChatMessageItemProps.onStartEdit.html","deprecated":false},{"id":"namespace_chatmessageitemprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageItemProps.onEndEdit","file":"src/components/chat/ChatMessageItem.tsx","doc":"","url":"./src/components/chat/ChatMessageItem.tsx/~/ChatMessageItemProps.onEndEdit.html","deprecated":false},{"id":"namespace_chatmessageitemprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageItemProps.onEdit","file":"src/components/chat/ChatMessageItem.tsx","doc":"Called only when the text changed.","url":"./src/components/chat/ChatMessageItem.tsx/~/ChatMessageItemProps.onEdit.html","deprecated":false},{"id":"namespace_chatmessageitemprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageItemProps.onDelete","file":"src/components/chat/ChatMessageItem.tsx","doc":"Called once the user has confirmed.","url":"./src/components/chat/ChatMessageItem.tsx/~/ChatMessageItemProps.onDelete.html","deprecated":false},{"id":"namespace_chatmessageitemprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageItemProps.onReply","file":"src/components/chat/ChatMessageItem.tsx","doc":"","url":"./src/components/chat/ChatMessageItem.tsx/~/ChatMessageItemProps.onReply.html","deprecated":false},{"id":"namespace_chatmessageitemprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatMessageItemProps.onJumpTo","file":"src/components/chat/ChatMessageItem.tsx","doc":"","url":"./src/components/chat/ChatMessageItem.tsx/~/ChatMessageItemProps.onJumpTo.html","deprecated":false},{"id":"namespace_chatmessageitem","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"ChatMessageItem","file":"src/components/chat/ChatMessageItem.tsx","doc":"Renders a chat message, or the editor over its text while editing. Its height eases between the two. Deleting asks for confirmation first.","url":"./src/components/chat/ChatMessageItem.tsx/~/ChatMessageItem.html","deprecated":false},{"id":"namespace_chatmodalprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ChatModalProps","file":"src/components/chat/ChatModal.tsx","doc":"Passed to ChatModal by ChatProvider.","url":"./src/components/chat/ChatModal.tsx/~/ChatModalProps.html","deprecated":false},{"id":"namespace_chatmodalprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatModalProps.onClose","file":"src/components/chat/ChatModal.tsx","doc":"Closes the chat, and drops the ?chat= deep link if there is one.","url":"./src/components/chat/ChatModal.tsx/~/ChatModalProps.onClose.html","deprecated":false},{"id":"namespace_chatmodalprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatModalProps.focusId","file":"src/components/chat/ChatModal.tsx","doc":"The message to open on, from a ?chat=<id> deep link. Ignored when it isn't in the first page of history.","url":"./src/components/chat/ChatModal.tsx/~/ChatModalProps.focusId.html","deprecated":false},{"id":"namespace_chatmodal","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"ChatModal","file":"src/components/chat/ChatModal.tsx","doc":"Renders the chat, opening on focusId's message, or on the \"new\" divider, when it is more than a screen above the bottom, else at the bottom. Reaching the bottom of a visible tab moves the read marker. The draft and its reply target survive closing and reloading (utils/chat/draft.ts). While it is open in a visible tab, the server sends the user no notification for the mentions they see live.","url":"./src/components/chat/ChatModal.tsx/~/ChatModal.html","deprecated":false},{"id":"namespace_pendingitemprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PendingItemProps","file":"src/components/chat/PendingItem.tsx","doc":"Passed to PendingItem by ChatModal for each of WSChatContext's pendingChatMessages.","url":"./src/components/chat/PendingItem.tsx/~/PendingItemProps.html","deprecated":false},{"id":"namespace_pendingitemprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PendingItemProps.pending","file":"src/components/chat/PendingItem.tsx","doc":"","url":"./src/components/chat/PendingItem.tsx/~/PendingItemProps.pending.html","deprecated":false},{"id":"namespace_pendingitemprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PendingItemProps.grouped","file":"src/components/chat/PendingItem.tsx","doc":"Set when it continues the user's run, which hides the avatar and name.","url":"./src/components/chat/PendingItem.tsx/~/PendingItemProps.grouped.html","deprecated":false},{"id":"namespace_pendingitemprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PendingItemProps.user","file":"src/components/chat/PendingItem.tsx","doc":"The signed-in user, who sent it.","url":"./src/components/chat/PendingItem.tsx/~/PendingItemProps.user.html","deprecated":false},{"id":"namespace_pendingitemprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PendingItemProps.onRetry","file":"src/components/chat/PendingItem.tsx","doc":"","url":"./src/components/chat/PendingItem.tsx/~/PendingItemProps.onRetry.html","deprecated":false},{"id":"namespace_pendingitemprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PendingItemProps.onDiscard","file":"src/components/chat/PendingItem.tsx","doc":"","url":"./src/components/chat/PendingItem.tsx/~/PendingItemProps.onDiscard.html","deprecated":false},{"id":"namespace_pendingitemprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PendingItemProps.onRestore","file":"src/components/chat/PendingItem.tsx","doc":"Takes the failed text back into the composer, and discards it.","url":"./src/components/chat/PendingItem.tsx/~/PendingItemProps.onRestore.html","deprecated":false},{"id":"namespace_pendingitemprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PendingItemProps.onJumpTo","file":"src/components/chat/PendingItem.tsx","doc":"","url":"./src/components/chat/PendingItem.tsx/~/PendingItemProps.onJumpTo.html","deprecated":false},{"id":"namespace_pendingitem","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"PendingItem","file":"src/components/chat/PendingItem.tsx","doc":"Renders a pending message, dimmed while it is sending. Once it has failed, it shows why and offers to retry it, edit it in the composer, or discard it.","url":"./src/components/chat/PendingItem.tsx/~/PendingItem.html","deprecated":false},{"id":"namespace_replyrefprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ReplyRefProps","file":"src/components/chat/ReplyRef.tsx","doc":"Passed to ReplyRef by ChatMessageItem, from the message's replyTo* fields, and by PendingItem, from its replyTo.","url":"./src/components/chat/ReplyRef.tsx/~/ReplyRefProps.html","deprecated":false},{"id":"namespace_replyrefprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ReplyRefProps.replyToId","file":"src/components/chat/ReplyRef.tsx","doc":"","url":"./src/components/chat/ReplyRef.tsx/~/ReplyRefProps.replyToId.html","deprecated":false},{"id":"namespace_replyrefprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ReplyRefProps.author","file":"src/components/chat/ReplyRef.tsx","doc":"Undefined when the replied-to message was deleted.","url":"./src/components/chat/ReplyRef.tsx/~/ReplyRefProps.author.html","deprecated":false},{"id":"namespace_replyrefprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ReplyRefProps.body","file":"src/components/chat/ReplyRef.tsx","doc":"Possibly cut short by the server, as replyToBody is.","url":"./src/components/chat/ReplyRef.tsx/~/ReplyRefProps.body.html","deprecated":false},{"id":"namespace_replyrefprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ReplyRefProps.onJumpTo","file":"src/components/chat/ReplyRef.tsx","doc":"","url":"./src/components/chat/ReplyRef.tsx/~/ReplyRefProps.onJumpTo.html","deprecated":false},{"id":"namespace_replyref","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"ReplyRef","file":"src/components/chat/ReplyRef.tsx","doc":"Renders the replied-to message's author and a one-line snippet of its text, as a button that scrolls to it. When it was deleted, the button is disabled and says so.","url":"./src/components/chat/ReplyRef.tsx/~/ReplyRef.html","deprecated":false},{"id":"namespace_commentformprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CommentFormProps","file":"src/components/comment/CommentForm.tsx","doc":"Passed to CommentForm by CommentThread, for a new comment, and by CommentNode, for a reply.","url":"./src/components/comment/CommentForm.tsx/~/CommentFormProps.html","deprecated":false},{"id":"namespace_commentformprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentFormProps.onSubmit","file":"src/components/comment/CommentForm.tsx","doc":"Sends the text. The form empties itself once it resolves. When it throws, as expectOk does, the form keeps the text and shows the error under errorTitle.","url":"./src/components/comment/CommentForm.tsx/~/CommentFormProps.onSubmit.html","deprecated":false},{"id":"namespace_commentformprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentFormProps.submitLabel","file":"src/components/comment/CommentForm.tsx","doc":"","url":"./src/components/comment/CommentForm.tsx/~/CommentFormProps.submitLabel.html","deprecated":false},{"id":"namespace_commentformprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentFormProps.pendingLabel","file":"src/components/comment/CommentForm.tsx","doc":"","url":"./src/components/comment/CommentForm.tsx/~/CommentFormProps.pendingLabel.html","deprecated":false},{"id":"namespace_commentformprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentFormProps.errorTitle","file":"src/components/comment/CommentForm.tsx","doc":"","url":"./src/components/comment/CommentForm.tsx/~/CommentFormProps.errorTitle.html","deprecated":false},{"id":"namespace_commentformprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentFormProps.placeholder","file":"src/components/comment/CommentForm.tsx","doc":"","url":"./src/components/comment/CommentForm.tsx/~/CommentFormProps.placeholder.html","deprecated":false},{"id":"namespace_commentformprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentFormProps.onCancel","file":"src/components/comment/CommentForm.tsx","doc":"Without it, the form has no Cancel button.","url":"./src/components/comment/CommentForm.tsx/~/CommentFormProps.onCancel.html","deprecated":false},{"id":"namespace_commentformprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentFormProps.cancelWhenEmpty","file":"src/components/comment/CommentForm.tsx","doc":"Shows Cancel only once there is text to throw away, and doesn't cancel on Escape. For the new-comment form, which has nothing to close.","url":"./src/components/comment/CommentForm.tsx/~/CommentFormProps.cancelWhenEmpty.html","deprecated":false},{"id":"namespace_commentformprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentFormProps.editorRef","file":"src/components/comment/CommentForm.tsx","doc":"","url":"./src/components/comment/CommentForm.tsx/~/CommentFormProps.editorRef.html","deprecated":false},{"id":"namespace_commentformprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentFormProps.layout","file":"src/components/comment/CommentForm.tsx","doc":"top puts leading beside the editor, for the new-comment form. inline is for replies, inside a comment.","url":"./src/components/comment/CommentForm.tsx/~/CommentFormProps.layout.html","deprecated":false},{"id":"namespace_commentformprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentFormProps.leading","file":"src/components/comment/CommentForm.tsx","doc":"","url":"./src/components/comment/CommentForm.tsx/~/CommentFormProps.leading.html","deprecated":false},{"id":"namespace_commentformprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentFormProps.className","file":"src/components/comment/CommentForm.tsx","doc":"Applies to the inline layout only.","url":"./src/components/comment/CommentForm.tsx/~/CommentFormProps.className.html","deprecated":false},{"id":"namespace_commentform","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"CommentForm","file":"src/components/comment/CommentForm.tsx","doc":"Renders a comment editor and its submit button, disabled while the text is blank or longer than VALIDATION.COMMENT_BODY_MAX.","url":"./src/components/comment/CommentForm.tsx/~/CommentForm.html","deprecated":false},{"id":"namespace_commentnodeprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CommentNodeProps","file":"src/components/comment/CommentNode.tsx","doc":"Passed to CommentNode by CommentThread for each top-level comment, and by CommentNode for each reply. The callbacks are CommentThread's, passed down unchanged.","url":"./src/components/comment/CommentNode.tsx/~/CommentNodeProps.html","deprecated":false},{"id":"namespace_commentnodeprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentNodeProps.comment","file":"src/components/comment/CommentNode.tsx","doc":"","url":"./src/components/comment/CommentNode.tsx/~/CommentNodeProps.comment.html","deprecated":false},{"id":"namespace_commentnodeprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentNodeProps.tree","file":"src/components/comment/CommentNode.tsx","doc":"The replies of every comment, by parent id, from CommentThread.","url":"./src/components/comment/CommentNode.tsx/~/CommentNodeProps.tree.html","deprecated":false},{"id":"namespace_commentnodeprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentNodeProps.depth","file":"src/components/comment/CommentNode.tsx","doc":"Sets the replies' --depth: the deeper, the narrower their indent.","url":"./src/components/comment/CommentNode.tsx/~/CommentNodeProps.depth.html","deprecated":false},{"id":"namespace_commentnodeprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentNodeProps.dumpId","file":"src/components/comment/CommentNode.tsx","doc":"","url":"./src/components/comment/CommentNode.tsx/~/CommentNodeProps.dumpId.html","deprecated":false},{"id":"namespace_commentnodeprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentNodeProps.currentUser","file":"src/components/comment/CommentNode.tsx","doc":"","url":"./src/components/comment/CommentNode.tsx/~/CommentNodeProps.currentUser.html","deprecated":false},{"id":"namespace_commentnodeprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentNodeProps.onCommentCreated","file":"src/components/comment/CommentNode.tsx","doc":"","url":"./src/components/comment/CommentNode.tsx/~/CommentNodeProps.onCommentCreated.html","deprecated":false},{"id":"namespace_commentnodeprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentNodeProps.onCommentDeleted","file":"src/components/comment/CommentNode.tsx","doc":"","url":"./src/components/comment/CommentNode.tsx/~/CommentNodeProps.onCommentDeleted.html","deprecated":false},{"id":"namespace_commentnodeprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentNodeProps.onCommentUpdated","file":"src/components/comment/CommentNode.tsx","doc":"","url":"./src/components/comment/CommentNode.tsx/~/CommentNodeProps.onCommentUpdated.html","deprecated":false},{"id":"namespace_commentnode","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"CommentNode","file":"src/components/comment/CommentNode.tsx","doc":"Renders a comment with its like button, and the reply, edit and delete actions for whoever may use them. Its author and moderators may edit and delete it. A deleted comment shows as \"[deleted]\", with its replies. The element's id, comment-<id>, is the anchor notifications link to.","url":"./src/components/comment/CommentNode.tsx/~/CommentNode.html","deprecated":false},{"id":"namespace_commentthreadprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CommentThreadProps","file":"src/components/comment/CommentThread.tsx","doc":"Passed to CommentThread by the Dump page, which holds the comments. The page applies the changes this user makes through the callbacks, and the ones others make from the socket's comment events, so a change can come both ways and must be applied once.","url":"./src/components/comment/CommentThread.tsx/~/CommentThreadProps.html","deprecated":false},{"id":"namespace_commentthreadprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentThreadProps.dumpId","file":"src/components/comment/CommentThread.tsx","doc":"","url":"./src/components/comment/CommentThread.tsx/~/CommentThreadProps.dumpId.html","deprecated":false},{"id":"namespace_commentthreadprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentThreadProps.comments","file":"src/components/comment/CommentThread.tsx","doc":"Every comment on the dump, flat and oldest first, deleted ones included so their replies keep their place.","url":"./src/components/comment/CommentThread.tsx/~/CommentThreadProps.comments.html","deprecated":false},{"id":"namespace_commentthreadprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentThreadProps.currentUser","file":"src/components/comment/CommentThread.tsx","doc":"","url":"./src/components/comment/CommentThread.tsx/~/CommentThreadProps.currentUser.html","deprecated":false},{"id":"namespace_commentthreadprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentThreadProps.onCommentCreated","file":"src/components/comment/CommentThread.tsx","doc":"","url":"./src/components/comment/CommentThread.tsx/~/CommentThreadProps.onCommentCreated.html","deprecated":false},{"id":"namespace_commentthreadprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentThreadProps.onCommentDeleted","file":"src/components/comment/CommentThread.tsx","doc":"","url":"./src/components/comment/CommentThread.tsx/~/CommentThreadProps.onCommentDeleted.html","deprecated":false},{"id":"namespace_commentthreadprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentThreadProps.onCommentUpdated","file":"src/components/comment/CommentThread.tsx","doc":"","url":"./src/components/comment/CommentThread.tsx/~/CommentThreadProps.onCommentUpdated.html","deprecated":false},{"id":"namespace_commentthread","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"CommentThread","file":"src/components/comment/CommentThread.tsx","doc":"Renders the comment count, the form that posts a comment when someone is signed in, and the tree of CommentNode.","url":"./src/components/comment/CommentThread.tsx/~/CommentThread.html","deprecated":false},{"id":"namespace_dumpcardprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"DumpCardProps","file":"src/components/dump/DumpCard.tsx","doc":"Passed to DumpCard by each list of dumps. The vote state comes from the parent, usually WSContext's passed down through the feed's props.","url":"./src/components/dump/DumpCard.tsx/~/DumpCardProps.html","deprecated":false},{"id":"namespace_dumpcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpCardProps.dump","file":"src/components/dump/DumpCard.tsx","doc":"","url":"./src/components/dump/DumpCard.tsx/~/DumpCardProps.dump.html","deprecated":false},{"id":"namespace_dumpcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpCardProps.voteCount","file":"src/components/dump/DumpCard.tsx","doc":"The socket's live count if it has one, else dump.voteCount.","url":"./src/components/dump/DumpCard.tsx/~/DumpCardProps.voteCount.html","deprecated":false},{"id":"namespace_dumpcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpCardProps.voted","file":"src/components/dump/DumpCard.tsx","doc":"","url":"./src/components/dump/DumpCard.tsx/~/DumpCardProps.voted.html","deprecated":false},{"id":"namespace_dumpcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpCardProps.canVote","file":"src/components/dump/DumpCard.tsx","doc":"","url":"./src/components/dump/DumpCard.tsx/~/DumpCardProps.canVote.html","deprecated":false},{"id":"namespace_dumpcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpCardProps.castVote","file":"src/components/dump/DumpCard.tsx","doc":"","url":"./src/components/dump/DumpCard.tsx/~/DumpCardProps.castVote.html","deprecated":false},{"id":"namespace_dumpcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpCardProps.removeVote","file":"src/components/dump/DumpCard.tsx","doc":"","url":"./src/components/dump/DumpCard.tsx/~/DumpCardProps.removeVote.html","deprecated":false},{"id":"namespace_dumpcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpCardProps.className","file":"src/components/dump/DumpCard.tsx","doc":"","url":"./src/components/dump/DumpCard.tsx/~/DumpCardProps.className.html","deprecated":false},{"id":"namespace_dumpcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpCardProps.isOwner","file":"src/components/dump/DumpCard.tsx","doc":"Hides the unread dot and shows the \"private\" badge.","url":"./src/components/dump/DumpCard.tsx/~/DumpCardProps.isOwner.html","deprecated":false},{"id":"namespace_dumpcard","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"DumpCard","file":"src/components/dump/DumpCard.tsx","doc":"Renders a dump as a card that opens the dump when clicked. A ctrl-click or middle click opens it in a new tab (useDumpCardLink). The card is an <li>, for a <ul>. It is memoized because feeds re-render on every live event, so its vote callbacks must be stable (WSContext's are).","url":"./src/components/dump/DumpCard.tsx/~/DumpCard.html","deprecated":false},{"id":"namespace_livedumpcardprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"LiveDumpCardProps","file":"src/components/dump/DumpCardList.tsx","doc":"Passed to LiveDumpCard by DumpCardList, and by PlaylistDumpList, which wraps each card in its drag handle and buttons.","url":"./src/components/dump/DumpCardList.tsx/~/LiveDumpCardProps.html","deprecated":false},{"id":"namespace_livedumpcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"LiveDumpCardProps.dump","file":"src/components/dump/DumpCardList.tsx","doc":"","url":"./src/components/dump/DumpCardList.tsx/~/LiveDumpCardProps.dump.html","deprecated":false},{"id":"namespace_livedumpcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"LiveDumpCardProps.className","file":"src/components/dump/DumpCardList.tsx","doc":"It comes from fadeClassName for a fading card.","url":"./src/components/dump/DumpCardList.tsx/~/LiveDumpCardProps.className.html","deprecated":false},{"id":"namespace_livedumpcard","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"LiveDumpCard","file":"src/components/dump/DumpCardList.tsx","doc":"Renders dump as a DumpCard, an <li>. The vote counts and calls come from WSContext, a dump missing from its counts showing its fetched voteCount. Voting takes a signed-in user, and a card is its owner's when it is the signed-in user's own dump.","url":"./src/components/dump/DumpCardList.tsx/~/LiveDumpCard.html","deprecated":false},{"id":"namespace_dumpcardlistprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"DumpCardListProps","file":"src/components/dump/DumpCardList.tsx","doc":"Passed to DumpCardList by every plain list of dump cards.","url":"./src/components/dump/DumpCardList.tsx/~/DumpCardListProps.html","deprecated":false},{"id":"namespace_dumpcardlistprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpCardListProps.dumps","file":"src/components/dump/DumpCardList.tsx","doc":"","url":"./src/components/dump/DumpCardList.tsx/~/DumpCardListProps.dumps.html","deprecated":false},{"id":"namespace_dumpcardlistprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpCardListProps.cardClassName","file":"src/components/dump/DumpCardList.tsx","doc":"Gives a card a class, as fadeClassName gives a fading one.","url":"./src/components/dump/DumpCardList.tsx/~/DumpCardListProps.cardClassName.html","deprecated":false},{"id":"namespace_dumpcardlist","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"DumpCardList","file":"src/components/dump/DumpCardList.tsx","doc":"Renders dumps as a .dump-feed of LiveDumpCard.","url":"./src/components/dump/DumpCardList.tsx/~/DumpCardList.html","deprecated":false},{"id":"namespace_filepreviewprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"FilePreviewProps","file":"src/components/dump/FilePreview.tsx","doc":"Passed to FilePreview by DumpCard (compact), by Dump (global) and by DumpEdit (neither).","url":"./src/components/dump/FilePreview.tsx/~/FilePreviewProps.html","deprecated":false},{"id":"namespace_filepreviewprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FilePreviewProps.dump","file":"src/components/dump/FilePreview.tsx","doc":"Expected to be a file dump. A link dump has no fileMime, so it shows as a download.","url":"./src/components/dump/FilePreview.tsx/~/FilePreviewProps.dump.html","deprecated":false},{"id":"namespace_filepreviewprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FilePreviewProps.compact","file":"src/components/dump/FilePreview.tsx","doc":"Shows a card's thumbnail, whose play button uses the global player.","url":"./src/components/dump/FilePreview.tsx/~/FilePreviewProps.compact.html","deprecated":false},{"id":"namespace_filepreviewprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FilePreviewProps.global","file":"src/components/dump/FilePreview.tsx","doc":"Plays full-size audio and video in the global player, not inline.","url":"./src/components/dump/FilePreview.tsx/~/FilePreviewProps.global.html","deprecated":false},{"id":"namespace_filepreview","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"FilePreview","file":"src/components/dump/FilePreview.tsx","doc":"Renders an uploaded file by its MIME type. Compact, it is a thumbnail or an icon. Full size, it is the image, a player, the embedded PDF, or a download link for anything else. File URLs carry the viewer's media token, so private files load too.","url":"./src/components/dump/FilePreview.tsx/~/FilePreview.html","deprecated":false},{"id":"namespace_journalcardprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"JournalCardProps","file":"src/components/dump/JournalCard.tsx","doc":"Passed to JournalCard by JournalFeed, with the vote state Index takes from WSContext, as for DumpCard.","url":"./src/components/dump/JournalCard.tsx/~/JournalCardProps.html","deprecated":false},{"id":"namespace_journalcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"JournalCardProps.dump","file":"src/components/dump/JournalCard.tsx","doc":"","url":"./src/components/dump/JournalCard.tsx/~/JournalCardProps.dump.html","deprecated":false},{"id":"namespace_journalcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"JournalCardProps.shape","file":"src/components/dump/JournalCard.tsx","doc":"From composeJournal. It sets the tile's grid span, not its look.","url":"./src/components/dump/JournalCard.tsx/~/JournalCardProps.shape.html","deprecated":false},{"id":"namespace_journalcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"JournalCardProps.voteCount","file":"src/components/dump/JournalCard.tsx","doc":"The socket's live count if it has one, else dump.voteCount.","url":"./src/components/dump/JournalCard.tsx/~/JournalCardProps.voteCount.html","deprecated":false},{"id":"namespace_journalcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"JournalCardProps.voted","file":"src/components/dump/JournalCard.tsx","doc":"","url":"./src/components/dump/JournalCard.tsx/~/JournalCardProps.voted.html","deprecated":false},{"id":"namespace_journalcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"JournalCardProps.canVote","file":"src/components/dump/JournalCard.tsx","doc":"","url":"./src/components/dump/JournalCard.tsx/~/JournalCardProps.canVote.html","deprecated":false},{"id":"namespace_journalcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"JournalCardProps.castVote","file":"src/components/dump/JournalCard.tsx","doc":"","url":"./src/components/dump/JournalCard.tsx/~/JournalCardProps.castVote.html","deprecated":false},{"id":"namespace_journalcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"JournalCardProps.removeVote","file":"src/components/dump/JournalCard.tsx","doc":"","url":"./src/components/dump/JournalCard.tsx/~/JournalCardProps.removeVote.html","deprecated":false},{"id":"namespace_journalcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"JournalCardProps.isOwner","file":"src/components/dump/JournalCard.tsx","doc":"Hides the unread dot and shows the \"private\" badge.","url":"./src/components/dump/JournalCard.tsx/~/JournalCardProps.isOwner.html","deprecated":false},{"id":"namespace_journalcard","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"JournalCard","file":"src/components/dump/JournalCard.tsx","doc":"Renders a dump as an image, a pull-quote or a text tile, depending on whether it has a thumbnail or a note. Clicking an image tile plays its media when it can, a link's or an uploaded audio or video file, and pauses a file once it plays; any other tile opens the dump. It is memoized like DumpCard, so its vote callbacks must be stable.","url":"./src/components/dump/JournalCard.tsx/~/JournalCard.html","deprecated":false},{"id":"namespace_newdumpbutton","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"NewDumpButton","file":"src/components/dump/NewDumpButton.tsx","doc":"Renders a \"+ New dump\" button, as NewPlaylistButton does for playlists, that opens DumpCreateModal. The modal hands the new dump to WSContext itself, so the button takes no callback.","url":"./src/components/dump/NewDumpButton.tsx/~/NewDumpButton.html","deprecated":false},{"id":"namespace_richcontentcardprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"RichContentCardProps","file":"src/components/dump/RichContentCard.tsx","doc":"Passed to RichContentCard by DumpCard (compact), Dump, DumpEdit and DumpCreateModal, the last two without a dump to play from.","url":"./src/components/dump/RichContentCard.tsx/~/RichContentCardProps.html","deprecated":false},{"id":"namespace_richcontentcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RichContentCardProps.richContent","file":"src/components/dump/RichContentCard.tsx","doc":"","url":"./src/components/dump/RichContentCard.tsx/~/RichContentCardProps.richContent.html","deprecated":false},{"id":"namespace_richcontentcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RichContentCardProps.compact","file":"src/components/dump/RichContentCard.tsx","doc":"Shows a card's thumbnail alone, as a play button or a link out.","url":"./src/components/dump/RichContentCard.tsx/~/RichContentCardProps.compact.html","deprecated":false},{"id":"namespace_richcontentcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RichContentCardProps.thumbnailOverrideUrl","file":"src/components/dump/RichContentCard.tsx","doc":"The dump's uploaded thumbnail, shown instead of the provider's and used as the player's artwork.","url":"./src/components/dump/RichContentCard.tsx/~/RichContentCardProps.thumbnailOverrideUrl.html","deprecated":false},{"id":"namespace_richcontentcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RichContentCardProps.dumpHref","file":"src/components/dump/RichContentCard.tsx","doc":"The dump's page, which the global player's title links to.","url":"./src/components/dump/RichContentCard.tsx/~/RichContentCardProps.dumpHref.html","deprecated":false},{"id":"namespace_richcontentcard","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"RichContentCard","file":"src/components/dump/RichContentCard.tsx","doc":"Renders a link's preview. Its thumbnail plays the media in the global player when it can be played, and otherwise opens the link in a new tab. Full size, it also shows the site, title and description, linking out.","url":"./src/components/dump/RichContentCard.tsx/~/RichContentCard.html","deprecated":false},{"id":"namespace_dumpcreatemodalprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"DumpCreateModalProps","file":"src/components/dump/create/DumpCreateModal.tsx","doc":"Passed to DumpCreateModal by the button that opens it. The parent unmounts the modal on onClose, which the modal also calls after a confirmed dismissal.","url":"./src/components/dump/create/DumpCreateModal.tsx/~/DumpCreateModalProps.html","deprecated":false},{"id":"namespace_dumpcreatemodalprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpCreateModalProps.onClose","file":"src/components/dump/create/DumpCreateModal.tsx","doc":"","url":"./src/components/dump/create/DumpCreateModal.tsx/~/DumpCreateModalProps.onClose.html","deprecated":false},{"id":"namespace_dumpcreatemodalprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpCreateModalProps.initialUrl","file":"src/components/dump/create/DumpCreateModal.tsx","doc":"A link shared from Android's share sheet, which AppHeader passes on from Index. It replaces any saved draft.","url":"./src/components/dump/create/DumpCreateModal.tsx/~/DumpCreateModalProps.initialUrl.html","deprecated":false},{"id":"namespace_dumpcreatemodal","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"DumpCreateModal","file":"src/components/dump/create/DumpCreateModal.tsx","doc":"Renders the dump creation modal. The first panel takes a link, previewed through GET /api/remote/preview and checked against GET /api/dumps?url=, or a file. The second takes the \"why\", categories and visibility, and posts to POST /api/dumps. The third adds the new dump to playlists. The new dump is handed to WSContext's injectDump so the feeds show it at once. Everything but the file is saved as a draft (utils/dump/draft.ts) until it is posted.","url":"./src/components/dump/create/DumpCreateModal.tsx/~/DumpCreateModal.html","deprecated":false},{"id":"namespace_duplicatenoticeprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"DuplicateNoticeProps","file":"src/components/dump/create/DuplicateNotice.tsx","doc":"Passed to DuplicateNotice by DumpCreateModal, with the matches of GET /api/dumps?url=.","url":"./src/components/dump/create/DuplicateNotice.tsx/~/DuplicateNoticeProps.html","deprecated":false},{"id":"namespace_duplicatenoticeprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DuplicateNoticeProps.matches","file":"src/components/dump/create/DuplicateNotice.tsx","doc":"Non-empty, latest first: the notice links the first one.","url":"./src/components/dump/create/DuplicateNotice.tsx/~/DuplicateNoticeProps.matches.html","deprecated":false},{"id":"namespace_duplicatenoticeprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DuplicateNoticeProps.onNavigate","file":"src/components/dump/create/DuplicateNotice.tsx","doc":"Closes the modal when the poster follows the link.","url":"./src/components/dump/create/DuplicateNotice.tsx/~/DuplicateNoticeProps.onNavigate.html","deprecated":false},{"id":"namespace_duplicatenotice","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"DuplicateNotice","file":"src/components/dump/create/DuplicateNotice.tsx","doc":"Renders the \"already dumped\" hint. It doesn't block posting, since a repost is sometimes on purpose.","url":"./src/components/dump/create/DuplicateNotice.tsx/~/DuplicateNotice.html","deprecated":false},{"id":"namespace_localfilepreviewprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"LocalFilePreviewProps","file":"src/components/dump/create/LocalFilePreview.tsx","doc":"Passed to LocalFilePreview by DumpCreateModal.","url":"./src/components/dump/create/LocalFilePreview.tsx/~/LocalFilePreviewProps.html","deprecated":false},{"id":"namespace_localfilepreviewprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"LocalFilePreviewProps.file","file":"src/components/dump/create/LocalFilePreview.tsx","doc":"","url":"./src/components/dump/create/LocalFilePreview.tsx/~/LocalFilePreviewProps.file.html","deprecated":false},{"id":"namespace_localfilepreview","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"LocalFilePreview","file":"src/components/dump/create/LocalFilePreview.tsx","doc":"Renders an image, video or audio file from a blob URL, which it revokes when file changes or it unmounts. Any other file renders nothing.","url":"./src/components/dump/create/LocalFilePreview.tsx/~/LocalFilePreview.html","deprecated":false},{"id":"namespace_step","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"Step","file":"src/components/dump/create/StepIndicator.tsx","doc":"A panel of DumpCreateModal, in the order they are walked. Categories and visibility have a panel of their own, \"details\", because behind a disclosure they went untouched.","url":"./src/components/dump/create/StepIndicator.tsx/~/Step.html","deprecated":false},{"id":"namespace_stepindicatorprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"StepIndicatorProps","file":"src/components/dump/create/StepIndicator.tsx","doc":"Passed to StepIndicator by DumpCreateModal.","url":"./src/components/dump/create/StepIndicator.tsx/~/StepIndicatorProps.html","deprecated":false},{"id":"namespace_stepindicatorprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"StepIndicatorProps.current","file":"src/components/dump/create/StepIndicator.tsx","doc":"","url":"./src/components/dump/create/StepIndicator.tsx/~/StepIndicatorProps.current.html","deprecated":false},{"id":"namespace_stepindicator","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"StepIndicator","file":"src/components/dump/create/StepIndicator.tsx","doc":"Renders the three panels as numbered steps, the passed ones ticked.","url":"./src/components/dump/create/StepIndicator.tsx/~/StepIndicator.html","deprecated":false},{"id":"namespace_titlefieldprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"TitleFieldProps","file":"src/components/dump/create/TitleField.tsx","doc":"Passed to TitleField by DumpCreateModal, which owns the editing state: it marks the title as the poster's own on onEdit.","url":"./src/components/dump/create/TitleField.tsx/~/TitleFieldProps.html","deprecated":false},{"id":"namespace_titlefieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TitleFieldProps.registration","file":"src/components/dump/create/TitleField.tsx","doc":"","url":"./src/components/dump/create/TitleField.tsx/~/TitleFieldProps.registration.html","deprecated":false},{"id":"namespace_titlefieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TitleFieldProps.editing","file":"src/components/dump/create/TitleField.tsx","doc":"","url":"./src/components/dump/create/TitleField.tsx/~/TitleFieldProps.editing.html","deprecated":false},{"id":"namespace_titlefieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TitleFieldProps.onEdit","file":"src/components/dump/create/TitleField.tsx","doc":"","url":"./src/components/dump/create/TitleField.tsx/~/TitleFieldProps.onEdit.html","deprecated":false},{"id":"namespace_titlefieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TitleFieldProps.onReset","file":"src/components/dump/create/TitleField.tsx","doc":"Puts the suggested title back. Without it, no reset button shows.","url":"./src/components/dump/create/TitleField.tsx/~/TitleFieldProps.onReset.html","deprecated":false},{"id":"namespace_titlefieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TitleFieldProps.disabled","file":"src/components/dump/create/TitleField.tsx","doc":"","url":"./src/components/dump/create/TitleField.tsx/~/TitleFieldProps.disabled.html","deprecated":false},{"id":"namespace_titlefield","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"TitleField","file":"src/components/dump/create/TitleField.tsx","doc":"Renders the title of a link or file dump. The suggested title, from the link's preview or the file's name, stays read-only until the ✎ button is pressed, so stray typing can't change it.","url":"./src/components/dump/create/TitleField.tsx/~/TitleField.html","deprecated":false},{"id":"namespace_emojipickerpopupprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"EmojiPickerPopupProps","file":"src/components/editor/EmojiPickerPopup.tsx","doc":"Passed to EmojiPickerPopup by TextEditor, which keeps the refs to detect outside presses, focus the search and step the keyboard into the grid.","url":"./src/components/editor/EmojiPickerPopup.tsx/~/EmojiPickerPopupProps.html","deprecated":false},{"id":"namespace_emojipickerpopupprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmojiPickerPopupProps.floatRef","file":"src/components/editor/EmojiPickerPopup.tsx","doc":"","url":"./src/components/editor/EmojiPickerPopup.tsx/~/EmojiPickerPopupProps.floatRef.html","deprecated":false},{"id":"namespace_emojipickerpopupprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmojiPickerPopupProps.searchRef","file":"src/components/editor/EmojiPickerPopup.tsx","doc":"","url":"./src/components/editor/EmojiPickerPopup.tsx/~/EmojiPickerPopupProps.searchRef.html","deprecated":false},{"id":"namespace_emojipickerpopupprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmojiPickerPopupProps.viewportRef","file":"src/components/editor/EmojiPickerPopup.tsx","doc":"Focused by TextEditor to hand the arrow keys to frimousse.","url":"./src/components/editor/EmojiPickerPopup.tsx/~/EmojiPickerPopupProps.viewportRef.html","deprecated":false},{"id":"namespace_emojipickerpopupprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmojiPickerPopupProps.style","file":"src/components/editor/EmojiPickerPopup.tsx","doc":"From useAnchoredFloat, or hidden until it has placed the picker.","url":"./src/components/editor/EmojiPickerPopup.tsx/~/EmojiPickerPopupProps.style.html","deprecated":false},{"id":"namespace_emojipickerpopupprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmojiPickerPopupProps.inline","file":"src/components/editor/EmojiPickerPopup.tsx","doc":"Set for a :query typed in the textarea. The search field then only mirrors query and can't take focus.","url":"./src/components/editor/EmojiPickerPopup.tsx/~/EmojiPickerPopupProps.inline.html","deprecated":false},{"id":"namespace_emojipickerpopupprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmojiPickerPopupProps.query","file":"src/components/editor/EmojiPickerPopup.tsx","doc":"","url":"./src/components/editor/EmojiPickerPopup.tsx/~/EmojiPickerPopupProps.query.html","deprecated":false},{"id":"namespace_emojipickerpopupprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmojiPickerPopupProps.onQueryChange","file":"src/components/editor/EmojiPickerPopup.tsx","doc":"","url":"./src/components/editor/EmojiPickerPopup.tsx/~/EmojiPickerPopupProps.onQueryChange.html","deprecated":false},{"id":"namespace_emojipickerpopupprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmojiPickerPopupProps.onSelect","file":"src/components/editor/EmojiPickerPopup.tsx","doc":"","url":"./src/components/editor/EmojiPickerPopup.tsx/~/EmojiPickerPopupProps.onSelect.html","deprecated":false},{"id":"namespace_emojipickerpopupprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmojiPickerPopupProps.onClose","file":"src/components/editor/EmojiPickerPopup.tsx","doc":"","url":"./src/components/editor/EmojiPickerPopup.tsx/~/EmojiPickerPopupProps.onClose.html","deprecated":false},{"id":"namespace_emojipickerpopupprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"EmojiPickerPopupProps.onKeyDownCapture","file":"src/components/editor/EmojiPickerPopup.tsx","doc":"Runs before frimousse sees the key, so it can take Escape and Enter.","url":"./src/components/editor/EmojiPickerPopup.tsx/~/EmojiPickerPopupProps.onKeyDownCapture.html","deprecated":false},{"id":"namespace_emojipickerpopup","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"EmojiPickerPopup","file":"src/components/editor/EmojiPickerPopup.tsx","doc":"Renders the picker in the current locale, with the skin tone last picked on this device. It fetches its emoji data from the site itself, where the Vite build copies it (VITE_EMOJIBASE_URL).","url":"./src/components/editor/EmojiPickerPopup.tsx/~/EmojiPickerPopup.html","deprecated":false},{"id":"namespace_markdownprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"MarkdownProps","file":"src/components/editor/Markdown.tsx","doc":"Passed to Markdown by any component that shows a user's text.","url":"./src/components/editor/Markdown.tsx/~/MarkdownProps.html","deprecated":false},{"id":"namespace_markdownprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"MarkdownProps.children","file":"src/components/editor/Markdown.tsx","doc":"","url":"./src/components/editor/Markdown.tsx/~/MarkdownProps.children.html","deprecated":false},{"id":"namespace_markdownprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"MarkdownProps.className","file":"src/components/editor/Markdown.tsx","doc":"","url":"./src/components/editor/Markdown.tsx/~/MarkdownProps.className.html","deprecated":false},{"id":"namespace_markdownprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"MarkdownProps.inline","file":"src/components/editor/Markdown.tsx","doc":"Drops the images, for a line-clamped teaser in a card, where an image would break the layout. The full text is one click away.","url":"./src/components/editor/Markdown.tsx/~/MarkdownProps.inline.html","deprecated":false},{"id":"namespace_markdownprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"MarkdownProps.everyone","file":"src/components/editor/Markdown.tsx","doc":"Shows @everyone as a mention, from a chat message's mentionsEveryone. Without it, @everyone is plain text: anyone may type it, and it reaches no one.","url":"./src/components/editor/Markdown.tsx/~/MarkdownProps.everyone.html","deprecated":false},{"id":"namespace_markdown","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"Markdown","file":"src/components/editor/Markdown.tsx","doc":"Renders GFM with @mentions as profile links and single newlines kept. It is memoized because parsing runs the whole remark pipeline, and the text rarely changes when its parent re-renders.","url":"./src/components/editor/Markdown.tsx/~/Markdown.html","deprecated":false},{"id":"namespace_mentiondropdownprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"MentionDropdownProps","file":"src/components/editor/MentionDropdown.tsx","doc":"Passed to MentionDropdown by TextEditor, from the state of useMentionAutocomplete.","url":"./src/components/editor/MentionDropdown.tsx/~/MentionDropdownProps.html","deprecated":false},{"id":"namespace_mentiondropdownprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"MentionDropdownProps.id","file":"src/components/editor/MentionDropdown.tsx","doc":"The textarea's aria-controls. Option i gets the id ${id}-${i}, which the textarea names as its aria-activedescendant.","url":"./src/components/editor/MentionDropdown.tsx/~/MentionDropdownProps.id.html","deprecated":false},{"id":"namespace_mentiondropdownprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"MentionDropdownProps.results","file":"src/components/editor/MentionDropdown.tsx","doc":"","url":"./src/components/editor/MentionDropdown.tsx/~/MentionDropdownProps.results.html","deprecated":false},{"id":"namespace_mentiondropdownprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"MentionDropdownProps.selectedIndex","file":"src/components/editor/MentionDropdown.tsx","doc":"","url":"./src/components/editor/MentionDropdown.tsx/~/MentionDropdownProps.selectedIndex.html","deprecated":false},{"id":"namespace_mentiondropdownprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"MentionDropdownProps.onSelect","file":"src/components/editor/MentionDropdown.tsx","doc":"","url":"./src/components/editor/MentionDropdown.tsx/~/MentionDropdownProps.onSelect.html","deprecated":false},{"id":"namespace_mentiondropdownprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"MentionDropdownProps.style","file":"src/components/editor/MentionDropdown.tsx","doc":"From useAnchoredFloat, or hidden until it has placed the list.","url":"./src/components/editor/MentionDropdown.tsx/~/MentionDropdownProps.style.html","deprecated":false},{"id":"namespace_mentiondropdown","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"MentionDropdown","file":"src/components/editor/MentionDropdown.tsx","doc":"Renders the matching users as a listbox, scrolled to keep the highlighted one in view, or nothing when none match. The keyboard stays in the textarea.","url":"./src/components/editor/MentionDropdown.tsx/~/MentionDropdown.html","deprecated":false},{"id":"namespace_texteditorhandle","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"TextEditorHandle","file":"src/components/editor/TextEditor.tsx","doc":"Exposed through the ref of TextEditor, so that the component that opens an editor (a reply, an edit, the chat composer) can focus it.","url":"./src/components/editor/TextEditor.tsx/~/TextEditorHandle.html","deprecated":false},{"id":"namespace_texteditorhandle","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"TextEditorHandle.focus","file":"src/components/editor/TextEditor.tsx","doc":"Focuses the textarea. atEnd puts the caret after the last character and scrolls the text there. preventScroll leaves the page and its scrollers where they are.","url":"./src/components/editor/TextEditor.tsx/~/TextEditorHandle.focus.html","deprecated":false},{"id":"namespace_texteditorprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"TextEditorProps","file":"src/components/editor/TextEditor.tsx","doc":"Passed to TextEditor by the component that owns the text, which keeps it in its state (the editor is controlled).","url":"./src/components/editor/TextEditor.tsx/~/TextEditorProps.html","deprecated":false},{"id":"namespace_texteditorprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TextEditorProps.value","file":"src/components/editor/TextEditor.tsx","doc":"","url":"./src/components/editor/TextEditor.tsx/~/TextEditorProps.value.html","deprecated":false},{"id":"namespace_texteditorprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TextEditorProps.onChange","file":"src/components/editor/TextEditor.tsx","doc":"Called on typing, and with the Markdown of the images once uploaded.","url":"./src/components/editor/TextEditor.tsx/~/TextEditorProps.onChange.html","deprecated":false},{"id":"namespace_texteditorprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TextEditorProps.placeholder","file":"src/components/editor/TextEditor.tsx","doc":"","url":"./src/components/editor/TextEditor.tsx/~/TextEditorProps.placeholder.html","deprecated":false},{"id":"namespace_texteditorprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TextEditorProps.disabled","file":"src/components/editor/TextEditor.tsx","doc":"","url":"./src/components/editor/TextEditor.tsx/~/TextEditorProps.disabled.html","deprecated":false},{"id":"namespace_texteditorprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TextEditorProps.rows","file":"src/components/editor/TextEditor.tsx","doc":"","url":"./src/components/editor/TextEditor.tsx/~/TextEditorProps.rows.html","deprecated":false},{"id":"namespace_texteditorprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TextEditorProps.id","file":"src/components/editor/TextEditor.tsx","doc":"","url":"./src/components/editor/TextEditor.tsx/~/TextEditorProps.id.html","deprecated":false},{"id":"namespace_texteditorprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TextEditorProps.className","file":"src/components/editor/TextEditor.tsx","doc":"","url":"./src/components/editor/TextEditor.tsx/~/TextEditorProps.className.html","deprecated":false},{"id":"namespace_texteditorprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TextEditorProps.autoResize","file":"src/components/editor/TextEditor.tsx","doc":"Grows the textarea with its text instead of scrolling it.","url":"./src/components/editor/TextEditor.tsx/~/TextEditorProps.autoResize.html","deprecated":false},{"id":"namespace_texteditorprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TextEditorProps.onSubmit","file":"src/components/editor/TextEditor.tsx","doc":"Called on Ctrl/Cmd+Enter, but not while an image is still uploading.","url":"./src/components/editor/TextEditor.tsx/~/TextEditorProps.onSubmit.html","deprecated":false},{"id":"namespace_texteditorprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TextEditorProps.onCancel","file":"src/components/editor/TextEditor.tsx","doc":"Called on Escape when no popup of the editor is left to close. Inline editors (an edit, a reply) pass it to mean \"never mind\".","url":"./src/components/editor/TextEditor.tsx/~/TextEditorProps.onCancel.html","deprecated":false},{"id":"namespace_texteditorprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TextEditorProps.onKeyDown","file":"src/components/editor/TextEditor.tsx","doc":"Runs after the editor's own keys (autocompletes, Ctrl+Enter), and never while an IME is composing, so an Enter that confirms a candidate isn't taken for \"send\".","url":"./src/components/editor/TextEditor.tsx/~/TextEditorProps.onKeyDown.html","deprecated":false},{"id":"namespace_texteditorprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TextEditorProps.maxLength","file":"src/components/editor/TextEditor.tsx","doc":"Shows a counter and marks the textarea invalid past it. It doesn't stop the typing, so the caller must still refuse a longer text.","url":"./src/components/editor/TextEditor.tsx/~/TextEditorProps.maxLength.html","deprecated":false},{"id":"namespace_texteditorprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TextEditorProps.countFrom","file":"src/components/editor/TextEditor.tsx","doc":"The length from which the counter shows, 80% of maxLength by default: a standing \"0 / 5000\" is noise, but the counter should turn up well before the warning colour does.","url":"./src/components/editor/TextEditor.tsx/~/TextEditorProps.countFrom.html","deprecated":false},{"id":"namespace_texteditorprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TextEditorProps.mentionEveryone","file":"src/components/editor/TextEditor.tsx","doc":"Offers @everyone among the mention suggestions. The chat's composer sets it for a role with chat:everyone, the one place it notifies.","url":"./src/components/editor/TextEditor.tsx/~/TextEditorProps.mentionEveryone.html","deprecated":false},{"id":"namespace_texteditorprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TextEditorProps.aria-invalid","file":"src/components/editor/TextEditor.tsx","doc":"","url":"./src/components/editor/TextEditor.tsx/~/TextEditorProps.aria-invalid.html","deprecated":false},{"id":"namespace_texteditorprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TextEditorProps.aria-describedby","file":"src/components/editor/TextEditor.tsx","doc":"Joined with the id of the editor's own upload notice when it shows one.","url":"./src/components/editor/TextEditor.tsx/~/TextEditorProps.aria-describedby.html","deprecated":false},{"id":"namespace_texteditor","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"TextEditor","file":"src/components/editor/TextEditor.tsx","doc":"Renders a textarea that completes @mentions and :emoji, opens an emoji picker from its button, and counts characters near maxLength. A pasted or dropped image is uploaded to POST /api/attachments with the session's token and inserted as Markdown, so the editor must sit under AuthProvider. The textarea is read-only while an upload runs.","url":"./src/components/editor/TextEditor.tsx/~/TextEditor.html","deprecated":false},{"id":"namespace_federatedsigninprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"FederatedSignInProps","file":"src/components/federation/FederatedSignIn.tsx","doc":"Passed to FederatedSignIn by UserLogin and UserRegister.","url":"./src/components/federation/FederatedSignIn.tsx/~/FederatedSignInProps.html","deprecated":false},{"id":"namespace_federatedsigninprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FederatedSignInProps.inviteToken","file":"src/components/federation/FederatedSignIn.tsx","doc":"The invite the register page was opened with, which lets a user of any instance join; the login page has none, and offers the trusted instances.","url":"./src/components/federation/FederatedSignIn.tsx/~/FederatedSignInProps.inviteToken.html","deprecated":false},{"id":"namespace_federatedsignin","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"FederatedSignIn","file":"src/components/federation/FederatedSignIn.tsx","doc":"Renders a button per trusted instance (GET /api/federation/peers) and a field for any other's address. Either starts the sign-in (POST /api/federation/logins) and leaves for that instance's /authorize page, which sends the user back to /federation/callback.","url":"./src/components/federation/FederatedSignIn.tsx/~/FederatedSignIn.html","deprecated":false},{"id":"namespace_grantlist","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"GrantList","file":"src/components/federation/GrantList.tsx","doc":"Renders each instance (GET /api/me/grants), when it last signed the user in, and a button that withdraws it (DELETE /api/me/grants/:host), which signs them out there; signing in there again asks them again.","url":"./src/components/federation/GrantList.tsx/~/GrantList.html","deprecated":false},{"id":"namespace_peermanager","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"PeerManager","file":"src/components/federation/PeerManager.tsx","doc":"Renders each listed instance with its status, which a click changes (PUT /api/federation/peers), and a button that takes it off the lists (DELETE /api/federation/peers/:host), then a field that adds one. The server checks that it answers as a gerbeur, and the permission again. Without FEDERATION_INCOMING it lists and adds only blocked instances; the trusted ones are kept for when it is back.","url":"./src/components/federation/PeerManager.tsx/~/PeerManager.html","deprecated":false},{"id":"namespace_dumpfeedstate","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"DumpFeedState","file":"src/components/feed/DumpFeed.tsx","doc":"Held by usePagedList for Index's feed and for each section of FollowedFeed.","url":"./src/components/feed/DumpFeed.tsx/~/DumpFeedState.html","deprecated":false},{"id":"namespace_mainfeedprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"MainFeedProps","file":"src/components/feed/DumpFeed.tsx","doc":"Passed by Index to whichever of the \"hot\", \"new\" and \"journal\" tabs is showing. The tabs share this one state, so switching tabs doesn't refetch.","url":"./src/components/feed/DumpFeed.tsx/~/MainFeedProps.html","deprecated":false},{"id":"namespace_mainfeedprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"MainFeedProps.state","file":"src/components/feed/DumpFeed.tsx","doc":"The tabs read its status and paging, and show dumps instead of its items.","url":"./src/components/feed/DumpFeed.tsx/~/MainFeedProps.state.html","deprecated":false},{"id":"namespace_mainfeedprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"MainFeedProps.dumps","file":"src/components/feed/DumpFeed.tsx","doc":"It holds the loaded dumps, with those WSContext added since and without the deleted ones.","url":"./src/components/feed/DumpFeed.tsx/~/MainFeedProps.dumps.html","deprecated":false},{"id":"namespace_mainfeedprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"MainFeedProps.sentinelRef","file":"src/components/feed/DumpFeed.tsx","doc":"It comes from useInfiniteScroll, and goes after the last card.","url":"./src/components/feed/DumpFeed.tsx/~/MainFeedProps.sentinelRef.html","deprecated":false},{"id":"namespace_dumpfeedprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"DumpFeedProps","file":"src/components/feed/DumpFeed.tsx","doc":"Passed to DumpFeed by Index for the \"hot\" and \"new\" tabs. It adds the active tab, as order, to the state all tabs share.","url":"./src/components/feed/DumpFeed.tsx/~/DumpFeedProps.html","deprecated":false},{"id":"namespace_dumpfeedprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpFeedProps.order","file":"src/components/feed/DumpFeed.tsx","doc":"","url":"./src/components/feed/DumpFeed.tsx/~/DumpFeedProps.order.html","deprecated":false},{"id":"namespace_dumpfeed","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"DumpFeed","file":"src/components/feed/DumpFeed.tsx","doc":"Renders the \"hot\" and \"new\" tabs as a DumpCardList, sorted on the client, followed by the infinite-scroll sentinel, or the loading, error or empty state. Index is its only user.","url":"./src/components/feed/DumpFeed.tsx/~/DumpFeed.html","deprecated":false},{"id":"namespace_feedfooterprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"FeedFooterProps","file":"src/components/feed/FeedFooter.tsx","doc":"Passed to FeedFooter by every list that loads its next page on scroll.","url":"./src/components/feed/FeedFooter.tsx/~/FeedFooterProps.html","deprecated":false},{"id":"namespace_feedfooterprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FeedFooterProps.hasMore","file":"src/components/feed/FeedFooter.tsx","doc":"","url":"./src/components/feed/FeedFooter.tsx/~/FeedFooterProps.hasMore.html","deprecated":false},{"id":"namespace_feedfooterprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FeedFooterProps.loadingMore","file":"src/components/feed/FeedFooter.tsx","doc":"","url":"./src/components/feed/FeedFooter.tsx/~/FeedFooterProps.loadingMore.html","deprecated":false},{"id":"namespace_feedfooterprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FeedFooterProps.sentinelRef","file":"src/components/feed/FeedFooter.tsx","doc":"It comes from useInfiniteScroll.","url":"./src/components/feed/FeedFooter.tsx/~/FeedFooterProps.sentinelRef.html","deprecated":false},{"id":"namespace_feedfooter","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"FeedFooter","file":"src/components/feed/FeedFooter.tsx","doc":"Renders the sentinel while there is more to load, \"Loading more…\" while it loads, and \"You've reached the end.\" once there is no more. The list renders it after a non-empty list only, since an empty list has its own message.","url":"./src/components/feed/FeedFooter.tsx/~/FeedFooter.html","deprecated":false},{"id":"namespace_feedtabbarprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"FeedTabBarProps","file":"src/components/feed/FeedTabBar.tsx","doc":"Passed to FeedTabBar by Index, from the URL it renders.","url":"./src/components/feed/FeedTabBar.tsx/~/FeedTabBarProps.html","deprecated":false},{"id":"namespace_feedtabbarprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FeedTabBarProps.categorySlug","file":"src/components/feed/FeedTabBar.tsx","doc":"The category whose feed is shown, or none for every dump.","url":"./src/components/feed/FeedTabBar.tsx/~/FeedTabBarProps.categorySlug.html","deprecated":false},{"id":"namespace_feedtabbarprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FeedTabBarProps.tab","file":"src/components/feed/FeedTabBar.tsx","doc":"The tab shown, the viewer's default one on a bare path.","url":"./src/components/feed/FeedTabBar.tsx/~/FeedTabBarProps.tab.html","deprecated":false},{"id":"namespace_feedtabbarprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FeedTabBarProps.followView","file":"src/components/feed/FeedTabBar.tsx","doc":"The view of the \"follow\" tab, which picking a category keeps.","url":"./src/components/feed/FeedTabBar.tsx/~/FeedTabBarProps.followView.html","deprecated":false},{"id":"namespace_feedtabbar","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"FeedTabBar","file":"src/components/feed/FeedTabBar.tsx","doc":"Renders the \"hot\", \"new\" and \"journal\" tabs, and \"followed\" for a signed-in user. A tab leads to the same scope: /new for every dump, /music/new for a category, and the viewer's default tab to the bare / or /music. A tab is a view of the same page, so it takes the place of the current history entry, while picking a category, another page, adds one and keeps the tab and its view, from /music/follow/playlists to /cinema/follow/playlists. Index renders it twice, in the header and below it, and CSS shows one by screen width.","url":"./src/components/feed/FeedTabBar.tsx/~/FeedTabBar.html","deprecated":false},{"id":"namespace_followedfeedprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"FollowedFeedProps","file":"src/components/feed/FollowedFeed.tsx","doc":"Passed to FollowedFeed by Index, which renders the tab for a signed-in user only. Unlike the other tabs, it loads its own dumps.","url":"./src/components/feed/FollowedFeed.tsx/~/FollowedFeedProps.html","deprecated":false},{"id":"namespace_followedfeedprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FollowedFeedProps.categorySlug","file":"src/components/feed/FollowedFeed.tsx","doc":"Scopes both views to a category.","url":"./src/components/feed/FollowedFeed.tsx/~/FollowedFeedProps.categorySlug.html","deprecated":false},{"id":"namespace_followedfeedprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FollowedFeedProps.view","file":"src/components/feed/FollowedFeed.tsx","doc":"The view the path names: /follow, or /follow/playlists.","url":"./src/components/feed/FollowedFeed.tsx/~/FollowedFeedProps.view.html","deprecated":false},{"id":"namespace_followedfeed","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"FollowedFeed","file":"src/components/feed/FollowedFeed.tsx","doc":"Renders the \"follow\" tab in two views, \"from people\" at /follow and \"from playlists\" at /follow/playlists, from GET /api/dumps?follow=users and GET /api/dumps?follow=playlists. Both load at once, so switching is instant, and each keeps its own pages, cached like the index's feed. Switching takes the place of the current history entry, as a tab does.","url":"./src/components/feed/FollowedFeed.tsx/~/FollowedFeed.html","deprecated":false},{"id":"namespace_journalfeed","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"JournalFeed","file":"src/components/feed/JournalFeed.tsx","doc":"Renders the feed Index passes as blocks of JournalCard, laid out by composeJournal, followed by the infinite-scroll sentinel, or the loading, error or empty state. The votes come from WSContext.","url":"./src/components/feed/JournalFeed.tsx/~/JournalFeed.html","deprecated":false},{"id":"namespace_presencerowprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PresenceRowProps","file":"src/components/feed/PresenceRow.tsx","doc":"Passed to PresenceRow by Index, which renders one in the header and one below it. Both selectors go to useRoomBeside.","url":"./src/components/feed/PresenceRow.tsx/~/PresenceRowProps.html","deprecated":false},{"id":"namespace_presencerowprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PresenceRowProps.fitWithin","file":"src/components/feed/PresenceRow.tsx","doc":"The ancestor that bounds the row the avatars share.","url":"./src/components/feed/PresenceRow.tsx/~/PresenceRowProps.fitWithin.html","deprecated":false},{"id":"namespace_presencerowprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PresenceRowProps.fitBeside","file":"src/components/feed/PresenceRow.tsx","doc":"The tabs, which keep their width before the avatars get any.","url":"./src/components/feed/PresenceRow.tsx/~/PresenceRowProps.fitBeside.html","deprecated":false},{"id":"namespace_presencerow","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"PresenceRow","file":"src/components/feed/PresenceRow.tsx","doc":"Renders the online users from WSContext as overlapping avatars linking to their profiles, as many as the tabs leave room for, and a \"+N\" counter for the others. It renders nothing when nobody is online.","url":"./src/components/feed/PresenceRow.tsx/~/PresenceRow.html","deprecated":false},{"id":"namespace_deletebuttonprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"DeleteButtonProps","file":"src/components/form/DeleteButton.tsx","doc":"Passed to DeleteButton by an edit form.","url":"./src/components/form/DeleteButton.tsx/~/DeleteButtonProps.html","deprecated":false},{"id":"namespace_deletebuttonprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DeleteButtonProps.label","file":"src/components/form/DeleteButton.tsx","doc":"Its accessible name, which names what goes, such as \"Delete dump\".","url":"./src/components/form/DeleteButton.tsx/~/DeleteButtonProps.label.html","deprecated":false},{"id":"namespace_deletebuttonprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DeleteButtonProps.onClick","file":"src/components/form/DeleteButton.tsx","doc":"Opens the page's confirmation, which deletes.","url":"./src/components/form/DeleteButton.tsx/~/DeleteButtonProps.onClick.html","deprecated":false},{"id":"namespace_deletebutton","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"DeleteButton","file":"src/components/form/DeleteButton.tsx","doc":"Renders a compact \"Delete\" button, at the start of the bar's .form-actions. A bar too narrow for it beside Cancel and Save shows its icon instead (.form-delete-icon).","url":"./src/components/form/DeleteButton.tsx/~/DeleteButton.html","deprecated":false},{"id":"namespace_filedropzoneprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"FileDropZoneProps","file":"src/components/form/FileDropZone.tsx","doc":"Passed to FileDropZone by FileField, from the form's state. The zone keeps no file of its own.","url":"./src/components/form/FileDropZone.tsx/~/FileDropZoneProps.html","deprecated":false},{"id":"namespace_filedropzoneprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FileDropZoneProps.file","file":"src/components/form/FileDropZone.tsx","doc":"","url":"./src/components/form/FileDropZone.tsx/~/FileDropZoneProps.file.html","deprecated":false},{"id":"namespace_filedropzoneprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FileDropZoneProps.onChange","file":"src/components/form/FileDropZone.tsx","doc":"Called with the file dropped or picked, or with null when it is removed.","url":"./src/components/form/FileDropZone.tsx/~/FileDropZoneProps.onChange.html","deprecated":false},{"id":"namespace_filedropzoneprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FileDropZoneProps.disabled","file":"src/components/form/FileDropZone.tsx","doc":"","url":"./src/components/form/FileDropZone.tsx/~/FileDropZoneProps.disabled.html","deprecated":false},{"id":"namespace_filedropzoneprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FileDropZoneProps.hint","file":"src/components/form/FileDropZone.tsx","doc":"Replaces the \"Drop a file here\" prompt.","url":"./src/components/form/FileDropZone.tsx/~/FileDropZoneProps.hint.html","deprecated":false},{"id":"namespace_filedropzoneprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FileDropZoneProps.maxBytes","file":"src/components/form/FileDropZone.tsx","doc":"Stated under the prompt when showLimit is on. FileField refuses a larger file.","url":"./src/components/form/FileDropZone.tsx/~/FileDropZoneProps.maxBytes.html","deprecated":false},{"id":"namespace_filedropzoneprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FileDropZoneProps.showLimit","file":"src/components/form/FileDropZone.tsx","doc":"","url":"./src/components/form/FileDropZone.tsx/~/FileDropZoneProps.showLimit.html","deprecated":false},{"id":"namespace_filedropzone","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"FileDropZone","file":"src/components/form/FileDropZone.tsx","doc":"Renders a zone that takes a dropped file, or opens the file picker on a click or Enter. Once a file is chosen, it shows its name and size and a button to remove it. Only the first of several dropped files is kept.","url":"./src/components/form/FileDropZone.tsx/~/FileDropZone.html","deprecated":false},{"id":"namespace_filefieldprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"FileFieldProps","file":"src/components/form/FileField.tsx","doc":"Passed to FileField by a dump form. The field it names holds the File itself, or null.","url":"./src/components/form/FileField.tsx/~/FileFieldProps.html","deprecated":false},{"id":"namespace_filefieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FileFieldProps.name","file":"src/components/form/FileField.tsx","doc":"","url":"./src/components/form/FileField.tsx/~/FileFieldProps.name.html","deprecated":false},{"id":"namespace_filefieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FileFieldProps.label","file":"src/components/form/FileField.tsx","doc":"","url":"./src/components/form/FileField.tsx/~/FileFieldProps.label.html","deprecated":false},{"id":"namespace_filefieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FileFieldProps.hint","file":"src/components/form/FileField.tsx","doc":"","url":"./src/components/form/FileField.tsx/~/FileFieldProps.hint.html","deprecated":false},{"id":"namespace_filefieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FileFieldProps.maxBytes","file":"src/components/form/FileField.tsx","doc":"Refuses a larger file, as a field error, as soon as it is picked.","url":"./src/components/form/FileField.tsx/~/FileFieldProps.maxBytes.html","deprecated":false},{"id":"namespace_filefieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FileFieldProps.showLimit","file":"src/components/form/FileField.tsx","doc":"States maxBytes in the drop zone.","url":"./src/components/form/FileField.tsx/~/FileFieldProps.showLimit.html","deprecated":false},{"id":"namespace_filefieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FileFieldProps.disabled","file":"src/components/form/FileField.tsx","doc":"","url":"./src/components/form/FileField.tsx/~/FileFieldProps.disabled.html","deprecated":false},{"id":"namespace_filefieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FileFieldProps.rules","file":"src/components/form/FileField.tsx","doc":"","url":"./src/components/form/FileField.tsx/~/FileFieldProps.rules.html","deprecated":false},{"id":"namespace_filefieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FileFieldProps.onValueChange","file":"src/components/form/FileField.tsx","doc":"Called after the form's value is set, for a side effect such as deriving the title from the file's name.","url":"./src/components/form/FileField.tsx/~/FileFieldProps.onValueChange.html","deprecated":false},{"id":"namespace_filefield","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"FileField","file":"src/components/form/FileField.tsx","doc":"Renders the drop zone with its label and the field's error. It must sit under a react-hook-form FormProvider, such as one given useApiForm's result.","url":"./src/components/form/FileField.tsx/~/FileField.html","deprecated":false},{"id":"namespace_formactionsprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"FormActionsProps","file":"src/components/form/FormActions.tsx","doc":"Passed to FormActions by a form, with its submit button as child.","url":"./src/components/form/FormActions.tsx/~/FormActionsProps.html","deprecated":false},{"id":"namespace_formactionsprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FormActionsProps.children","file":"src/components/form/FormActions.tsx","doc":"","url":"./src/components/form/FormActions.tsx/~/FormActionsProps.children.html","deprecated":false},{"id":"namespace_formactionsprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FormActionsProps.onCancel","file":"src/components/form/FormActions.tsx","doc":"Adds a Cancel button, which calls it.","url":"./src/components/form/FormActions.tsx/~/FormActionsProps.onCancel.html","deprecated":false},{"id":"namespace_formactionsprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FormActionsProps.cancelLabel","file":"src/components/form/FormActions.tsx","doc":"Replaces the \"Cancel\" label.","url":"./src/components/form/FormActions.tsx/~/FormActionsProps.cancelLabel.html","deprecated":false},{"id":"namespace_formactionsprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FormActionsProps.disabled","file":"src/components/form/FormActions.tsx","doc":"Disables the Cancel button only, not the children.","url":"./src/components/form/FormActions.tsx/~/FormActionsProps.disabled.html","deprecated":false},{"id":"namespace_formactions","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"FormActions","file":"src/components/form/FormActions.tsx","doc":"Renders the Cancel button, if any, then the children, aligned right. The Cancel button is type=\"button\", so it never submits the form.","url":"./src/components/form/FormActions.tsx/~/FormActions.html","deprecated":false},{"id":"namespace_formerrorprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"FormErrorProps","file":"src/components/form/FormError.tsx","doc":"Passed to FormError by a form, to say what failed.","url":"./src/components/form/FormError.tsx/~/FormErrorProps.html","deprecated":false},{"id":"namespace_formerrorprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FormErrorProps.title","file":"src/components/form/FormError.tsx","doc":"Replaces the \"Something went wrong\" title.","url":"./src/components/form/FormError.tsx/~/FormErrorProps.title.html","deprecated":false},{"id":"namespace_formerror","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"FormError","file":"src/components/form/FormError.tsx","doc":"Renders the form's root error as an ErrorCard, or nothing without one. useApiForm's submit sets that error when the request fails. It must sit under a react-hook-form FormProvider.","url":"./src/components/form/FormError.tsx/~/FormError.html","deprecated":false},{"id":"namespace_inlineeditprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"InlineEditProps","file":"src/components/form/InlineEdit.tsx","doc":"Passed to InlineEdit by the component showing the text, which renders it as children and saves it in onSave.","url":"./src/components/form/InlineEdit.tsx/~/InlineEditProps.html","deprecated":false},{"id":"namespace_inlineeditprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InlineEditProps.value","file":"src/components/form/InlineEdit.tsx","doc":"The text as saved, which the field opens on.","url":"./src/components/form/InlineEdit.tsx/~/InlineEditProps.value.html","deprecated":false},{"id":"namespace_inlineeditprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InlineEditProps.editable","file":"src/components/form/InlineEdit.tsx","doc":"Without it, children show alone.","url":"./src/components/form/InlineEdit.tsx/~/InlineEditProps.editable.html","deprecated":false},{"id":"namespace_inlineeditprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InlineEditProps.label","file":"src/components/form/InlineEdit.tsx","doc":"Names the action, such as \"Edit title\": the text's tooltip.","url":"./src/components/form/InlineEdit.tsx/~/InlineEditProps.label.html","deprecated":false},{"id":"namespace_inlineeditprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InlineEditProps.onSave","file":"src/components/form/InlineEdit.tsx","doc":"Saves the trimmed text, and shows it: the field closes once it resolves. A thrown error, such as expectOk's, stays open under the field. A text left as it was closes the field without calling it.","url":"./src/components/form/InlineEdit.tsx/~/InlineEditProps.onSave.html","deprecated":false},{"id":"namespace_inlineeditprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InlineEditProps.kind","file":"src/components/form/InlineEdit.tsx","doc":"A one-line field (text, email), where Enter saves, or the Markdown editor (markdown), where Ctrl/Cmd+Enter does. Escape cancels in both.","url":"./src/components/form/InlineEdit.tsx/~/InlineEditProps.kind.html","deprecated":false},{"id":"namespace_inlineeditprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InlineEditProps.required","file":"src/components/form/InlineEdit.tsx","doc":"Refuses to save an empty text.","url":"./src/components/form/InlineEdit.tsx/~/InlineEditProps.required.html","deprecated":false},{"id":"namespace_inlineeditprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InlineEditProps.maxLength","file":"src/components/form/InlineEdit.tsx","doc":"","url":"./src/components/form/InlineEdit.tsx/~/InlineEditProps.maxLength.html","deprecated":false},{"id":"namespace_inlineeditprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InlineEditProps.placeholder","file":"src/components/form/InlineEdit.tsx","doc":"","url":"./src/components/form/InlineEdit.tsx/~/InlineEditProps.placeholder.html","deprecated":false},{"id":"namespace_inlineeditprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InlineEditProps.className","file":"src/components/form/InlineEdit.tsx","doc":"Added to the wrapper, which the text and the field both sit in.","url":"./src/components/form/InlineEdit.tsx/~/InlineEditProps.className.html","deprecated":false},{"id":"namespace_inlineeditprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InlineEditProps.fieldClassName","file":"src/components/form/InlineEdit.tsx","doc":"Added to the field: see InlineEditFieldProps.","url":"./src/components/form/InlineEdit.tsx/~/InlineEditProps.fieldClassName.html","deprecated":false},{"id":"namespace_inlineeditprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InlineEditProps.children","file":"src/components/form/InlineEdit.tsx","doc":"","url":"./src/components/form/InlineEdit.tsx/~/InlineEditProps.children.html","deprecated":false},{"id":"namespace_inlineedit","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"InlineEdit","file":"src/components/form/InlineEdit.tsx","doc":"Renders children, which a click on them, or the ✎ button after them, swaps for a field holding value, with Save and Cancel under it. The ✎ shows on hover and on keyboard focus. A click on a link in the text, or one that ends a selection, follows the link or keeps the selection instead. Closing the field gives the focus back to the ✎ when the field had it.","url":"./src/components/form/InlineEdit.tsx/~/InlineEdit.html","deprecated":false},{"id":"namespace_inlineeditfieldprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"InlineEditFieldProps","file":"src/components/form/InlineEdit.tsx","doc":"Passed to InlineEditField by InlineEdit, and by the components that open it with an action of their own, CommentNode and ChatMessageItem, in place of the text while it is edited.","url":"./src/components/form/InlineEdit.tsx/~/InlineEditFieldProps.html","deprecated":false},{"id":"namespace_inlineeditfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InlineEditFieldProps.onSave","file":"src/components/form/InlineEdit.tsx","doc":"Saves the trimmed text. The field closes once it is done, and stays open under the error it throws. A text left as it was isn't passed to it.","url":"./src/components/form/InlineEdit.tsx/~/InlineEditFieldProps.onSave.html","deprecated":false},{"id":"namespace_inlineeditfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InlineEditFieldProps.onClose","file":"src/components/form/InlineEdit.tsx","doc":"Called once the text is saved, or left: the field is to unmount.","url":"./src/components/form/InlineEdit.tsx/~/InlineEditFieldProps.onClose.html","deprecated":false},{"id":"namespace_inlineeditfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InlineEditFieldProps.label","file":"src/components/form/InlineEdit.tsx","doc":"Names a one-line field, such as \"Edit title\".","url":"./src/components/form/InlineEdit.tsx/~/InlineEditFieldProps.label.html","deprecated":false},{"id":"namespace_inlineeditfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InlineEditFieldProps.fieldClassName","file":"src/components/form/InlineEdit.tsx","doc":"Added to the field: for a one-line one, the class of the text it edits, such as dump-title, so that it takes on its type in every style.","url":"./src/components/form/InlineEdit.tsx/~/InlineEditFieldProps.fieldClassName.html","deprecated":false},{"id":"namespace_inlineeditfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InlineEditFieldProps.enterSaves","file":"src/components/form/InlineEdit.tsx","doc":"In the Markdown editor, saves on Enter, a line breaking on Shift+Enter, as the chat's composer does. Ctrl/Cmd+Enter saves in either case.","url":"./src/components/form/InlineEdit.tsx/~/InlineEditFieldProps.enterSaves.html","deprecated":false},{"id":"namespace_inlineeditfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InlineEditFieldProps.countFrom","file":"src/components/form/InlineEdit.tsx","doc":"Where the Markdown editor's counter starts, near maxLength.","url":"./src/components/form/InlineEdit.tsx/~/InlineEditFieldProps.countFrom.html","deprecated":false},{"id":"namespace_inlineeditfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"InlineEditFieldProps.returnFocusTo","file":"src/components/form/InlineEdit.tsx","doc":"Takes the focus once the field is gone, if it had it and no one has taken it since: the button that opened it, back in its place.","url":"./src/components/form/InlineEdit.tsx/~/InlineEditFieldProps.returnFocusTo.html","deprecated":false},{"id":"namespace_inlineeditfield","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"InlineEditField","file":"src/components/form/InlineEdit.tsx","doc":"Renders the field holding value, focused with the caret at its end, and Save and Cancel under it. Enter saves a line, Ctrl/Cmd+Enter a Markdown text, Escape leaves. Saving is refused while the text is empty and required, or longer than maxLength. It is mounted afresh on each opening, so that it starts from value.","url":"./src/components/form/InlineEdit.tsx/~/InlineEditField.html","deprecated":false},{"id":"namespace_richtextfieldprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"RichTextFieldProps","file":"src/components/form/RichTextField.tsx","doc":"Passed to RichTextField by a form that holds a string field.","url":"./src/components/form/RichTextField.tsx/~/RichTextFieldProps.html","deprecated":false},{"id":"namespace_richtextfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RichTextFieldProps.name","file":"src/components/form/RichTextField.tsx","doc":"","url":"./src/components/form/RichTextField.tsx/~/RichTextFieldProps.name.html","deprecated":false},{"id":"namespace_richtextfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RichTextFieldProps.label","file":"src/components/form/RichTextField.tsx","doc":"","url":"./src/components/form/RichTextField.tsx/~/RichTextFieldProps.label.html","deprecated":false},{"id":"namespace_richtextfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RichTextFieldProps.placeholder","file":"src/components/form/RichTextField.tsx","doc":"","url":"./src/components/form/RichTextField.tsx/~/RichTextFieldProps.placeholder.html","deprecated":false},{"id":"namespace_richtextfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RichTextFieldProps.rows","file":"src/components/form/RichTextField.tsx","doc":"","url":"./src/components/form/RichTextField.tsx/~/RichTextFieldProps.rows.html","deprecated":false},{"id":"namespace_richtextfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RichTextFieldProps.maxLength","file":"src/components/form/RichTextField.tsx","doc":"Counted in the editor and checked on submit, with a message. It overrides a maxLength in rules.","url":"./src/components/form/RichTextField.tsx/~/RichTextFieldProps.maxLength.html","deprecated":false},{"id":"namespace_richtextfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RichTextFieldProps.autoResize","file":"src/components/form/RichTextField.tsx","doc":"","url":"./src/components/form/RichTextField.tsx/~/RichTextFieldProps.autoResize.html","deprecated":false},{"id":"namespace_richtextfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RichTextFieldProps.disabled","file":"src/components/form/RichTextField.tsx","doc":"","url":"./src/components/form/RichTextField.tsx/~/RichTextFieldProps.disabled.html","deprecated":false},{"id":"namespace_richtextfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RichTextFieldProps.rules","file":"src/components/form/RichTextField.tsx","doc":"","url":"./src/components/form/RichTextField.tsx/~/RichTextFieldProps.rules.html","deprecated":false},{"id":"namespace_richtextfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RichTextFieldProps.editorRef","file":"src/components/form/RichTextField.tsx","doc":"The editor's ref, for a caller that focuses it.","url":"./src/components/form/RichTextField.tsx/~/RichTextFieldProps.editorRef.html","deprecated":false},{"id":"namespace_richtextfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RichTextFieldProps.onSubmit","file":"src/components/form/RichTextField.tsx","doc":"Called on Ctrl/Cmd+Enter.","url":"./src/components/form/RichTextField.tsx/~/RichTextFieldProps.onSubmit.html","deprecated":false},{"id":"namespace_richtextfield","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"RichTextField","file":"src/components/form/RichTextField.tsx","doc":"Renders the editor with its label and the field's error. It must sit under a react-hook-form FormProvider, such as one given useApiForm's result.","url":"./src/components/form/RichTextField.tsx/~/RichTextField.html","deprecated":false},{"id":"namespace_segmentedfieldprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"SegmentedFieldProps","file":"src/components/form/SegmentedField.tsx","doc":"Passed to SegmentedField by a form, or by VisibilityToggle.","url":"./src/components/form/SegmentedField.tsx/~/SegmentedFieldProps.html","deprecated":false},{"id":"namespace_segmentedfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SegmentedFieldProps.name","file":"src/components/form/SegmentedField.tsx","doc":"","url":"./src/components/form/SegmentedField.tsx/~/SegmentedFieldProps.name.html","deprecated":false},{"id":"namespace_segmentedfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SegmentedFieldProps.options","file":"src/components/form/SegmentedField.tsx","doc":"","url":"./src/components/form/SegmentedField.tsx/~/SegmentedFieldProps.options.html","deprecated":false},{"id":"namespace_segmentedfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SegmentedFieldProps.label","file":"src/components/form/SegmentedField.tsx","doc":"","url":"./src/components/form/SegmentedField.tsx/~/SegmentedFieldProps.label.html","deprecated":false},{"id":"namespace_segmentedfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SegmentedFieldProps.disabled","file":"src/components/form/SegmentedField.tsx","doc":"","url":"./src/components/form/SegmentedField.tsx/~/SegmentedFieldProps.disabled.html","deprecated":false},{"id":"namespace_segmentedfield","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"SegmentedField","file":"src/components/form/SegmentedField.tsx","doc":"Renders a Segmented bound to the field name, under its label. It must sit under a react-hook-form FormProvider.","url":"./src/components/form/SegmentedField.tsx/~/SegmentedField.html","deprecated":false},{"id":"namespace_visibilitytoggleprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"VisibilityToggleProps","file":"src/components/form/SegmentedField.tsx","doc":"Passed to VisibilityToggle by a dump or playlist form.","url":"./src/components/form/SegmentedField.tsx/~/VisibilityToggleProps.html","deprecated":false},{"id":"namespace_visibilitytoggleprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VisibilityToggleProps.name","file":"src/components/form/SegmentedField.tsx","doc":"A boolean field, true for public.","url":"./src/components/form/SegmentedField.tsx/~/VisibilityToggleProps.name.html","deprecated":false},{"id":"namespace_visibilitytoggleprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VisibilityToggleProps.label","file":"src/components/form/SegmentedField.tsx","doc":"","url":"./src/components/form/SegmentedField.tsx/~/VisibilityToggleProps.label.html","deprecated":false},{"id":"namespace_visibilitytoggleprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VisibilityToggleProps.disabled","file":"src/components/form/SegmentedField.tsx","doc":"","url":"./src/components/form/SegmentedField.tsx/~/VisibilityToggleProps.disabled.html","deprecated":false},{"id":"namespace_visibilitytoggle","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"VisibilityToggle","file":"src/components/form/SegmentedField.tsx","doc":"Renders a Public/Private toggle on a boolean field that is true for public. A dump's API takes isPrivate instead, so the dump forms bind the toggle to an isPublic field and invert it on submit.","url":"./src/components/form/SegmentedField.tsx/~/VisibilityToggle.html","deprecated":false},{"id":"namespace_slugfieldprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"SlugFieldProps","file":"src/components/form/SlugField.tsx","doc":"Passed to SlugField by DumpEdit's and PlaylistEditForm's forms, which send the slug only when it differs from saved.slug.","url":"./src/components/form/SlugField.tsx/~/SlugFieldProps.html","deprecated":false},{"id":"namespace_slugfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SlugFieldProps.name","file":"src/components/form/SlugField.tsx","doc":"The form's slug field.","url":"./src/components/form/SlugField.tsx/~/SlugFieldProps.name.html","deprecated":false},{"id":"namespace_slugfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SlugFieldProps.titleName","file":"src/components/form/SlugField.tsx","doc":"The form's title field, which the slug follows until it is typed in.","url":"./src/components/form/SlugField.tsx/~/SlugFieldProps.titleName.html","deprecated":false},{"id":"namespace_slugfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SlugFieldProps.prefix","file":"src/components/form/SlugField.tsx","doc":"The page's path up to the slug, such as /@bob/dumps/.","url":"./src/components/form/SlugField.tsx/~/SlugFieldProps.prefix.html","deprecated":false},{"id":"namespace_slugfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SlugFieldProps.saved","file":"src/components/form/SlugField.tsx","doc":"The item as saved, whose slug a title put back to its own restores.","url":"./src/components/form/SlugField.tsx/~/SlugFieldProps.saved.html","deprecated":false},{"id":"namespace_slugfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SlugFieldProps.saved.title","file":"src/components/form/SlugField.tsx","doc":"","url":"./src/components/form/SlugField.tsx/~/SlugFieldProps.saved.title.html","deprecated":false},{"id":"namespace_slugfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SlugFieldProps.saved.slug","file":"src/components/form/SlugField.tsx","doc":"","url":"./src/components/form/SlugField.tsx/~/SlugFieldProps.saved.slug.html","deprecated":false},{"id":"namespace_slugfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SlugFieldProps.inputClassName","file":"src/components/form/SlugField.tsx","doc":"For a form outside .form, whose inputs take their own class.","url":"./src/components/form/SlugField.tsx/~/SlugFieldProps.inputClassName.html","deprecated":false},{"id":"namespace_slugfield","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"SlugField","file":"src/components/form/SlugField.tsx","doc":"Renders the slug's input after its path, and its error. Until the user types in it, it follows the title, proposing slugify(title), or the saved slug when the title slugifies as the saved one does. It must sit under a react-hook-form FormProvider.","url":"./src/components/form/SlugField.tsx/~/SlugField.html","deprecated":false},{"id":"namespace_submitbuttonprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"SubmitButtonProps","file":"src/components/form/SubmitButton.tsx","doc":"Passed to SubmitButton by a form, usually inside FormActions.","url":"./src/components/form/SubmitButton.tsx/~/SubmitButtonProps.html","deprecated":false},{"id":"namespace_submitbuttonprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SubmitButtonProps.children","file":"src/components/form/SubmitButton.tsx","doc":"","url":"./src/components/form/SubmitButton.tsx/~/SubmitButtonProps.children.html","deprecated":false},{"id":"namespace_submitbuttonprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SubmitButtonProps.pendingLabel","file":"src/components/form/SubmitButton.tsx","doc":"Replaces the label while the form is submitting, such as \"Saving…\".","url":"./src/components/form/SubmitButton.tsx/~/SubmitButtonProps.pendingLabel.html","deprecated":false},{"id":"namespace_submitbuttonprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SubmitButtonProps.disabled","file":"src/components/form/SubmitButton.tsx","doc":"Disables the button, which is disabled while submitting anyway.","url":"./src/components/form/SubmitButton.tsx/~/SubmitButtonProps.disabled.html","deprecated":false},{"id":"namespace_submitbuttonprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SubmitButtonProps.className","file":"src/components/form/SubmitButton.tsx","doc":"Replaces the btn-primary class.","url":"./src/components/form/SubmitButton.tsx/~/SubmitButtonProps.className.html","deprecated":false},{"id":"namespace_submitbuttonprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SubmitButtonProps.aria-label","file":"src/components/form/SubmitButton.tsx","doc":"Names an icon-only button, such as \"✓\".","url":"./src/components/form/SubmitButton.tsx/~/SubmitButtonProps.aria-label.html","deprecated":false},{"id":"namespace_submitbutton","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"SubmitButton","file":"src/components/form/SubmitButton.tsx","doc":"Renders a submit button that is disabled while the form submits, so that a second click can't post twice. It reads the form's state, so it must sit under a react-hook-form FormProvider.","url":"./src/components/form/SubmitButton.tsx/~/SubmitButton.html","deprecated":false},{"id":"namespace_textfieldprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"TextFieldProps","file":"src/components/form/TextField.tsx","doc":"Passed to TextField by a form that holds a string field.","url":"./src/components/form/TextField.tsx/~/TextFieldProps.html","deprecated":false},{"id":"namespace_textfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TextFieldProps.name","file":"src/components/form/TextField.tsx","doc":"","url":"./src/components/form/TextField.tsx/~/TextFieldProps.name.html","deprecated":false},{"id":"namespace_textfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TextFieldProps.label","file":"src/components/form/TextField.tsx","doc":"","url":"./src/components/form/TextField.tsx/~/TextFieldProps.label.html","deprecated":false},{"id":"namespace_textfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TextFieldProps.labelAction","file":"src/components/form/TextField.tsx","doc":"Shown at the right of the label, such as a reset button.","url":"./src/components/form/TextField.tsx/~/TextFieldProps.labelAction.html","deprecated":false},{"id":"namespace_textfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TextFieldProps.type","file":"src/components/form/TextField.tsx","doc":"","url":"./src/components/form/TextField.tsx/~/TextFieldProps.type.html","deprecated":false},{"id":"namespace_textfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TextFieldProps.placeholder","file":"src/components/form/TextField.tsx","doc":"","url":"./src/components/form/TextField.tsx/~/TextFieldProps.placeholder.html","deprecated":false},{"id":"namespace_textfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TextFieldProps.autoComplete","file":"src/components/form/TextField.tsx","doc":"","url":"./src/components/form/TextField.tsx/~/TextFieldProps.autoComplete.html","deprecated":false},{"id":"namespace_textfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TextFieldProps.autoFocus","file":"src/components/form/TextField.tsx","doc":"","url":"./src/components/form/TextField.tsx/~/TextFieldProps.autoFocus.html","deprecated":false},{"id":"namespace_textfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TextFieldProps.disabled","file":"src/components/form/TextField.tsx","doc":"","url":"./src/components/form/TextField.tsx/~/TextFieldProps.disabled.html","deprecated":false},{"id":"namespace_textfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TextFieldProps.rules","file":"src/components/form/TextField.tsx","doc":"","url":"./src/components/form/TextField.tsx/~/TextFieldProps.rules.html","deprecated":false},{"id":"namespace_textfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TextFieldProps.maxLength","file":"src/components/form/TextField.tsx","doc":"Stops the typing at this length, through the input's own maxLength. Unlike RichTextField's, it adds no rule, so a value set from code isn't checked.","url":"./src/components/form/TextField.tsx/~/TextFieldProps.maxLength.html","deprecated":false},{"id":"namespace_textfieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TextFieldProps.showCount","file":"src/components/form/TextField.tsx","doc":"Shows an n / maxLength counter, only when maxLength is set.","url":"./src/components/form/TextField.tsx/~/TextFieldProps.showCount.html","deprecated":false},{"id":"namespace_textfield","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"TextField","file":"src/components/form/TextField.tsx","doc":"Renders the input with its label and the field's error. It must sit under a react-hook-form FormProvider, such as one given useApiForm's result.","url":"./src/components/form/TextField.tsx/~/TextField.html","deprecated":false},{"id":"namespace_appheaderprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"AppHeaderProps","file":"src/components/layout/AppHeader.tsx","doc":"Passed to AppHeader by the index page. The other pages leave these props out.","url":"./src/components/layout/AppHeader.tsx/~/AppHeaderProps.html","deprecated":false},{"id":"namespace_appheaderprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AppHeaderProps.centerSlot","file":"src/components/layout/AppHeader.tsx","doc":"Shown beside the search. The index page puts its feed tabs there.","url":"./src/components/layout/AppHeader.tsx/~/AppHeaderProps.centerSlot.html","deprecated":false},{"id":"namespace_appheaderprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AppHeaderProps.disableNew","file":"src/components/layout/AppHeader.tsx","doc":"Set by the index page while its feed fails to load.","url":"./src/components/layout/AppHeader.tsx/~/AppHeaderProps.disableNew.html","deprecated":false},{"id":"namespace_appheaderprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AppHeaderProps.initialDumpUrl","file":"src/components/layout/AppHeader.tsx","doc":"Opens the dump creation dialog at mount, with this link. The index page passes the link shared to the app from Android's share sheet.","url":"./src/components/layout/AppHeader.tsx/~/AppHeaderProps.initialDumpUrl.html","deprecated":false},{"id":"namespace_appheader","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"AppHeader","file":"src/components/layout/AppHeader.tsx","doc":"Renders the site's header. It holds the search, which stays open on the results page and slides open under the header on small screens, the link to the playlists page, the signed-in user's menu and buttons or a guest's \"Log in\", and a banner while live updates are down. It also hosts the dump creation dialog that its \"+ Dump\" button opens.","url":"./src/components/layout/AppHeader.tsx/~/AppHeader.html","deprecated":false},{"id":"namespace_chatbutton","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"ChatButton","file":"src/components/layout/ChatButton.tsx","doc":"Renders the button that opens the chat, filled with the accent and dotted while the socket counts unread messages; the count itself is in its label. ChatFab takes over, with the count, once the header scrolls away.","url":"./src/components/layout/ChatButton.tsx/~/ChatButton.html","deprecated":false},{"id":"namespace_chatfab","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"ChatFab","file":"src/components/layout/ChatFab.tsx","doc":"Renders the chat button that floats above DumpFab once the header, and its ChatButton, have scrolled out of view. It renders nothing when signed out.","url":"./src/components/layout/ChatFab.tsx/~/ChatFab.html","deprecated":false},{"id":"namespace_dumpfab","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"DumpFab","file":"src/components/layout/DumpFab.tsx","doc":"Renders the button that opens the dump creation dialog once the header, and its \"+ Dump\" button, have scrolled out of view. It renders nothing when signed out. The stylesheet lifts it above the global player.","url":"./src/components/layout/DumpFab.tsx/~/DumpFab.html","deprecated":false},{"id":"namespace_marquee","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"Marquee","file":"src/components/layout/Marquee.tsx","doc":"Renders the marquee for a signed-in user in the GeoCities style, an empty band until the feed is loaded, so that the page under it doesn't move when it comes.","url":"./src/components/layout/Marquee.tsx/~/Marquee.html","deprecated":false},{"id":"namespace_naviconprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"NavIconProps","file":"src/components/layout/NavIcons.tsx","doc":"Passed to every icon, so a caller can add its own class (the bell rings).","url":"./src/components/layout/NavIcons.tsx/~/NavIconProps.html","deprecated":false},{"id":"namespace_naviconprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"NavIconProps.className","file":"src/components/layout/NavIcons.tsx","doc":"","url":"./src/components/layout/NavIcons.tsx/~/NavIconProps.className.html","deprecated":false},{"id":"namespace_iconsearch","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"IconSearch","file":"src/components/layout/NavIcons.tsx","doc":"Renders a magnifier, for the header's search toggle and the search bar.","url":"./src/components/layout/NavIcons.tsx/~/IconSearch.html","deprecated":false},{"id":"namespace_iconclose","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"IconClose","file":"src/components/layout/NavIcons.tsx","doc":"Renders the ✕ the search toggle turns into while the search is open.","url":"./src/components/layout/NavIcons.tsx/~/IconClose.html","deprecated":false},{"id":"namespace_iconchat","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"IconChat","file":"src/components/layout/NavIcons.tsx","doc":"Renders a speech bubble, for ChatButton and ChatFab.","url":"./src/components/layout/NavIcons.tsx/~/IconChat.html","deprecated":false},{"id":"namespace_iconbell","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"IconBell","file":"src/components/layout/NavIcons.tsx","doc":"Renders a bell, for NotificationBell.","url":"./src/components/layout/NavIcons.tsx/~/IconBell.html","deprecated":false},{"id":"namespace_notificationbell","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"NotificationBell","file":"src/components/layout/NotificationBell.tsx","doc":"Renders the bell that leads to /notifications. While the socket counts unread notifications it fills with the accent and wears a dot; the count itself is in its label and the tab's title. It rings when the socket pushes a new one.","url":"./src/components/layout/NotificationBell.tsx/~/NotificationBell.html","deprecated":false},{"id":"namespace_pageerrorprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PageErrorProps","file":"src/components/layout/PageError.tsx","doc":"Passed to PageError by a page whose load failed.","url":"./src/components/layout/PageError.tsx/~/PageErrorProps.html","deprecated":false},{"id":"namespace_pageerrorprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PageErrorProps.title","file":"src/components/layout/PageError.tsx","doc":"Defaults to \"Something went wrong\".","url":"./src/components/layout/PageError.tsx/~/PageErrorProps.title.html","deprecated":false},{"id":"namespace_pageerrorprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PageErrorProps.message","file":"src/components/layout/PageError.tsx","doc":"","url":"./src/components/layout/PageError.tsx/~/PageErrorProps.message.html","deprecated":false},{"id":"namespace_pageerrorprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PageErrorProps.actions","file":"src/components/layout/PageError.tsx","doc":"Buttons under the message, such as a retry.","url":"./src/components/layout/PageError.tsx/~/PageErrorProps.actions.html","deprecated":false},{"id":"namespace_pageerror","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"PageError","file":"src/components/layout/PageError.tsx","doc":"Renders an error card as the whole page, under the header, so the user can still navigate away.","url":"./src/components/layout/PageError.tsx/~/PageError.html","deprecated":false},{"id":"namespace_pagegroupprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PageGroupProps","file":"src/components/layout/PageGroup.tsx","doc":"Passed to PageGroup by Settings, Manage and Notifications.","url":"./src/components/layout/PageGroup.tsx/~/PageGroupProps.html","deprecated":false},{"id":"namespace_pagegroupprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PageGroupProps.label","file":"src/components/layout/PageGroup.tsx","doc":"It shows as a small capitalized label, ruled to the column's end.","url":"./src/components/layout/PageGroup.tsx/~/PageGroupProps.label.html","deprecated":false},{"id":"namespace_pagegroupprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PageGroupProps.children","file":"src/components/layout/PageGroup.tsx","doc":"Usually a .page-card, or the notifications' list of cards.","url":"./src/components/layout/PageGroup.tsx/~/PageGroupProps.children.html","deprecated":false},{"id":"namespace_pagegroup","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"PageGroup","file":"src/components/layout/PageGroup.tsx","doc":"Renders a <section> headed by label as its h2.","url":"./src/components/layout/PageGroup.tsx/~/PageGroup.html","deprecated":false},{"id":"namespace_pageheaderprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PageHeaderProps","file":"src/components/layout/PageHeader.tsx","doc":"Passed to PageHeader by Settings, Manage, Notifications and Playlists.","url":"./src/components/layout/PageHeader.tsx/~/PageHeaderProps.html","deprecated":false},{"id":"namespace_pageheaderprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PageHeaderProps.icon","file":"src/components/layout/PageHeader.tsx","doc":"An emoji before the title, hidden from screen readers.","url":"./src/components/layout/PageHeader.tsx/~/PageHeaderProps.icon.html","deprecated":false},{"id":"namespace_pageheaderprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PageHeaderProps.title","file":"src/components/layout/PageHeader.tsx","doc":"","url":"./src/components/layout/PageHeader.tsx/~/PageHeaderProps.title.html","deprecated":false},{"id":"namespace_pageheaderprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PageHeaderProps.children","file":"src/components/layout/PageHeader.tsx","doc":"It goes at the end of the row, such as the notifications' unread count or the playlists' category menu and order tabs.","url":"./src/components/layout/PageHeader.tsx/~/PageHeaderProps.children.html","deprecated":false},{"id":"namespace_pageheader","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"PageHeader","file":"src/components/layout/PageHeader.tsx","doc":"Renders the page's h1 with its icon, then children, as the first block of a PageShell: a narrow one's PageGroups follow it, or the playlists page's grid.","url":"./src/components/layout/PageHeader.tsx/~/PageHeader.html","deprecated":false},{"id":"namespace_pageshellprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PageShellProps","file":"src/components/layout/PageShell.tsx","doc":"Passed to PageShell by a page, around its content.","url":"./src/components/layout/PageShell.tsx/~/PageShellProps.html","deprecated":false},{"id":"namespace_pageshellprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PageShellProps.children","file":"src/components/layout/PageShell.tsx","doc":"","url":"./src/components/layout/PageShell.tsx/~/PageShellProps.children.html","deprecated":false},{"id":"namespace_pageshellprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PageShellProps.centered","file":"src/components/layout/PageShell.tsx","doc":"Centers the content, for a lone card such as a form or an error.","url":"./src/components/layout/PageShell.tsx/~/PageShellProps.centered.html","deprecated":false},{"id":"namespace_pageshellprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PageShellProps.narrow","file":"src/components/layout/PageShell.tsx","doc":"Narrows the content to the column the user menu's and the bell's pages share, under a PageHeader.","url":"./src/components/layout/PageShell.tsx/~/PageShellProps.narrow.html","deprecated":false},{"id":"namespace_pageshell","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"PageShell","file":"src/components/layout/PageShell.tsx","doc":"Renders AppHeader, then the page's content as the <main>.","url":"./src/components/layout/PageShell.tsx/~/PageShell.html","deprecated":false},{"id":"namespace_searchbarprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"SearchBarProps","file":"src/components/layout/SearchBar.tsx","doc":"Passed to SearchBar by AppHeader, which holds the query and decides where a search leads.","url":"./src/components/layout/SearchBar.tsx/~/SearchBarProps.html","deprecated":false},{"id":"namespace_searchbarprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SearchBarProps.expanded","file":"src/components/layout/SearchBar.tsx","doc":"","url":"./src/components/layout/SearchBar.tsx/~/SearchBarProps.expanded.html","deprecated":false},{"id":"namespace_searchbarprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SearchBarProps.value","file":"src/components/layout/SearchBar.tsx","doc":"","url":"./src/components/layout/SearchBar.tsx/~/SearchBarProps.value.html","deprecated":false},{"id":"namespace_searchbarprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SearchBarProps.onValueChange","file":"src/components/layout/SearchBar.tsx","doc":"","url":"./src/components/layout/SearchBar.tsx/~/SearchBarProps.onValueChange.html","deprecated":false},{"id":"namespace_searchbarprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SearchBarProps.onSubmit","file":"src/components/layout/SearchBar.tsx","doc":"Called with the trimmed query, never an empty one.","url":"./src/components/layout/SearchBar.tsx/~/SearchBarProps.onSubmit.html","deprecated":false},{"id":"namespace_searchbarprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SearchBarProps.onCancel","file":"src/components/layout/SearchBar.tsx","doc":"Called when Escape is pressed in the input.","url":"./src/components/layout/SearchBar.tsx/~/SearchBarProps.onCancel.html","deprecated":false},{"id":"namespace_searchbar","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"SearchBar","file":"src/components/layout/SearchBar.tsx","doc":"Renders the search form. AppHeader renders two over one state, one in its center and one in the row that slides open under it on small screens, so the query survives crossing the breakpoint. Opening it focuses the input.","url":"./src/components/layout/SearchBar.tsx/~/SearchBar.html","deprecated":false},{"id":"namespace_usermenuprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UserMenuProps","file":"src/components/layout/UserMenu.tsx","doc":"Passed to UserMenu by AppHeader, for a signed-in user.","url":"./src/components/layout/UserMenu.tsx/~/UserMenuProps.html","deprecated":false},{"id":"namespace_usermenuprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserMenuProps.user","file":"src/components/layout/UserMenu.tsx","doc":"","url":"./src/components/layout/UserMenu.tsx/~/UserMenuProps.user.html","deprecated":false},{"id":"namespace_usermenu","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"UserMenu","file":"src/components/layout/UserMenu.tsx","doc":"Renders the signed-in user's avatar, which opens a menu with links to their profile, /playlists, /community and /settings, to /manage for those who hold category:manage or federation:manage, and a Log out button. A click outside or Escape closes it.","url":"./src/components/layout/UserMenu.tsx/~/UserMenu.html","deprecated":false},{"id":"namespace_globalplayer","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"GlobalPlayer","file":"src/components/player/GlobalPlayer.tsx","doc":"Renders what PlayerContext plays, with a link to its dump: a MediaPlayer for a file or a stream, the provider's iframe for an embed, and the tracklist of the queue or of a YouTube playlist. It renders nothing while nothing plays.","url":"./src/components/player/GlobalPlayer.tsx/~/GlobalPlayer.html","deprecated":false},{"id":"namespace_mediaplayerprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"MediaPlayerProps","file":"src/components/player/MediaPlayer.tsx","doc":"Passed to MediaPlayer by GlobalPlayer, which wires the callbacks and the handles to PlayerContext, and by the file previews, which pass only the media.","url":"./src/components/player/MediaPlayer.tsx/~/MediaPlayerProps.html","deprecated":false},{"id":"namespace_mediaplayerprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"MediaPlayerProps.src","file":"src/components/player/MediaPlayer.tsx","doc":"","url":"./src/components/player/MediaPlayer.tsx/~/MediaPlayerProps.src.html","deprecated":false},{"id":"namespace_mediaplayerprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"MediaPlayerProps.kind","file":"src/components/player/MediaPlayer.tsx","doc":"","url":"./src/components/player/MediaPlayer.tsx/~/MediaPlayerProps.kind.html","deprecated":false},{"id":"namespace_mediaplayerprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"MediaPlayerProps.poster","file":"src/components/player/MediaPlayer.tsx","doc":"Shown before a video plays.","url":"./src/components/player/MediaPlayer.tsx/~/MediaPlayerProps.poster.html","deprecated":false},{"id":"namespace_mediaplayerprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"MediaPlayerProps.autoplay","file":"src/components/player/MediaPlayer.tsx","doc":"","url":"./src/components/player/MediaPlayer.tsx/~/MediaPlayerProps.autoplay.html","deprecated":false},{"id":"namespace_mediaplayerprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"MediaPlayerProps.startTime","file":"src/components/player/MediaPlayer.tsx","doc":"In seconds. Read on mount only: later seeks go through seekRef.","url":"./src/components/player/MediaPlayer.tsx/~/MediaPlayerProps.startTime.html","deprecated":false},{"id":"namespace_mediaplayerprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"MediaPlayerProps.onPlayStateChange","file":"src/components/player/MediaPlayer.tsx","doc":"","url":"./src/components/player/MediaPlayer.tsx/~/MediaPlayerProps.onPlayStateChange.html","deprecated":false},{"id":"namespace_mediaplayerprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"MediaPlayerProps.onTimeUpdate","file":"src/components/player/MediaPlayer.tsx","doc":"","url":"./src/components/player/MediaPlayer.tsx/~/MediaPlayerProps.onTimeUpdate.html","deprecated":false},{"id":"namespace_mediaplayerprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"MediaPlayerProps.onEnded","file":"src/components/player/MediaPlayer.tsx","doc":"Called at the media's end, where GlobalPlayer plays the next item.","url":"./src/components/player/MediaPlayer.tsx/~/MediaPlayerProps.onEnded.html","deprecated":false},{"id":"namespace_mediaplayerprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"MediaPlayerProps.onError","file":"src/components/player/MediaPlayer.tsx","doc":"Called when the media fails to load or decode, where a stream's URL is re-resolved.","url":"./src/components/player/MediaPlayer.tsx/~/MediaPlayerProps.onError.html","deprecated":false},{"id":"namespace_mediaplayerprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"MediaPlayerProps.waveform","file":"src/components/player/MediaPlayer.tsx","doc":"Where an audio file's waveform comes from. Without it, as for a stream whose bytes another site serves, audio seeks on a plain bar.","url":"./src/components/player/MediaPlayer.tsx/~/MediaPlayerProps.waveform.html","deprecated":false},{"id":"namespace_mediaplayerprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"MediaPlayerProps.seekRef","file":"src/components/player/MediaPlayer.tsx","doc":"Receives its seek handle while mounted, for PlayerContext's seekTo.","url":"./src/components/player/MediaPlayer.tsx/~/MediaPlayerProps.seekRef.html","deprecated":false},{"id":"namespace_mediaplayerprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"MediaPlayerProps.seekRef.current","file":"src/components/player/MediaPlayer.tsx","doc":"","url":"./src/components/player/MediaPlayer.tsx/~/MediaPlayerProps.seekRef.current.html","deprecated":false},{"id":"namespace_mediaplayerprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"MediaPlayerProps.toggleRef","file":"src/components/player/MediaPlayer.tsx","doc":"Receives its play/pause handle while mounted, for togglePlay.","url":"./src/components/player/MediaPlayer.tsx/~/MediaPlayerProps.toggleRef.html","deprecated":false},{"id":"namespace_mediaplayerprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"MediaPlayerProps.toggleRef.current","file":"src/components/player/MediaPlayer.tsx","doc":"","url":"./src/components/player/MediaPlayer.tsx/~/MediaPlayerProps.toggleRef.current.html","deprecated":false},{"id":"namespace_mediaplayer","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"MediaPlayer","file":"src/components/player/MediaPlayer.tsx","doc":"Renders a media element with the site's own controls. Audio seeks on its waveform when it has one; video gets a slim bar, a fullscreen button, and controls that hide while it plays. Whether it plays is read from the element's own events, so a media key or the OS's controls show too. The volume carries over to the next MediaPlayer, which matters since GlobalPlayer mounts a new one for each track.","url":"./src/components/player/MediaPlayer.tsx/~/MediaPlayer.html","deprecated":false},{"id":"namespace_iconplay","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"IconPlay","file":"src/components/player/PlayerIcons.tsx","doc":"Renders the play icon, nudged right so the triangle looks centred.","url":"./src/components/player/PlayerIcons.tsx/~/IconPlay.html","deprecated":false},{"id":"namespace_iconpause","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"IconPause","file":"src/components/player/PlayerIcons.tsx","doc":"Renders the pause icon, the play button's other state.","url":"./src/components/player/PlayerIcons.tsx/~/IconPause.html","deprecated":false},{"id":"namespace_iconvolumeprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"IconVolumeProps","file":"src/components/player/PlayerIcons.tsx","doc":"Passed to IconVolume by MediaPlayer's mute button.","url":"./src/components/player/PlayerIcons.tsx/~/IconVolumeProps.html","deprecated":false},{"id":"namespace_iconvolumeprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"IconVolumeProps.muted","file":"src/components/player/PlayerIcons.tsx","doc":"","url":"./src/components/player/PlayerIcons.tsx/~/IconVolumeProps.muted.html","deprecated":false},{"id":"namespace_iconvolume","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"IconVolume","file":"src/components/player/PlayerIcons.tsx","doc":"Renders the mute button's icon, crossed when muted.","url":"./src/components/player/PlayerIcons.tsx/~/IconVolume.html","deprecated":false},{"id":"namespace_iconfullscreen","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"IconFullscreen","file":"src/components/player/PlayerIcons.tsx","doc":"Renders the icon of a video's fullscreen button.","url":"./src/components/player/PlayerIcons.tsx/~/IconFullscreen.html","deprecated":false},{"id":"namespace_scrubberprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ScrubberProps","file":"src/components/player/Scrubber.tsx","doc":"Passed to Scrubber by MediaPlayer and FilePreview. Times are in seconds.","url":"./src/components/player/Scrubber.tsx/~/ScrubberProps.html","deprecated":false},{"id":"namespace_scrubberprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ScrubberProps.current","file":"src/components/player/Scrubber.tsx","doc":"","url":"./src/components/player/Scrubber.tsx/~/ScrubberProps.current.html","deprecated":false},{"id":"namespace_scrubberprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ScrubberProps.duration","file":"src/components/player/Scrubber.tsx","doc":"","url":"./src/components/player/Scrubber.tsx/~/ScrubberProps.duration.html","deprecated":false},{"id":"namespace_scrubberprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ScrubberProps.onSeek","file":"src/components/player/Scrubber.tsx","doc":"Called once a click, a drag or a key lands somewhere.","url":"./src/components/player/Scrubber.tsx/~/ScrubberProps.onSeek.html","deprecated":false},{"id":"namespace_scrubberprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ScrubberProps.onScrub","file":"src/components/player/Scrubber.tsx","doc":"Called with the time under the pointer while it holds the scrubber, and with null once it lets go, so MediaPlayer's clock can follow the drag.","url":"./src/components/player/Scrubber.tsx/~/ScrubberProps.onScrub.html","deprecated":false},{"id":"namespace_scrubberprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ScrubberProps.peaks","file":"src/components/player/Scrubber.tsx","doc":"The waveform's heights from 0 to 1; without them, a plain bar.","url":"./src/components/player/Scrubber.tsx/~/ScrubberProps.peaks.html","deprecated":false},{"id":"namespace_scrubberprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ScrubberProps.slim","file":"src/components/player/Scrubber.tsx","doc":"Draws the thin bar of a video's controls instead of the audio track.","url":"./src/components/player/Scrubber.tsx/~/ScrubberProps.slim.html","deprecated":false},{"id":"namespace_scrubber","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"Scrubber","file":"src/components/player/Scrubber.tsx","doc":"Renders a slider over the media's timeline. A pointer seeks where it lets go, showing where it is while held; arrows seek KEY_STEP seconds, Home and End to either end. The played part of the waveform is the same path clipped to the playhead by a nested <svg>, so it moves smoothly within a bar.","url":"./src/components/player/Scrubber.tsx/~/Scrubber.html","deprecated":false},{"id":"namespace_addtoplaylistmodalprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"AddToPlaylistModalProps","file":"src/components/playlist/AddToPlaylistModal.tsx","doc":"Passed to AddToPlaylistModal by the dump page.","url":"./src/components/playlist/AddToPlaylistModal.tsx/~/AddToPlaylistModalProps.html","deprecated":false},{"id":"namespace_addtoplaylistmodalprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AddToPlaylistModalProps.dumpId","file":"src/components/playlist/AddToPlaylistModal.tsx","doc":"","url":"./src/components/playlist/AddToPlaylistModal.tsx/~/AddToPlaylistModalProps.dumpId.html","deprecated":false},{"id":"namespace_addtoplaylistmodalprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AddToPlaylistModalProps.onClose","file":"src/components/playlist/AddToPlaylistModal.tsx","doc":"","url":"./src/components/playlist/AddToPlaylistModal.tsx/~/AddToPlaylistModalProps.onClose.html","deprecated":false},{"id":"namespace_addtoplaylistmodal","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"AddToPlaylistModal","file":"src/components/playlist/AddToPlaylistModal.tsx","doc":"Renders a PlaylistMembershipPanel in a modal, for the playlists usePlaylistMemberships loads and toggles.","url":"./src/components/playlist/AddToPlaylistModal.tsx/~/AddToPlaylistModal.html","deprecated":false},{"id":"namespace_newplaylistbuttonprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"NewPlaylistButtonProps","file":"src/components/playlist/NewPlaylistButton.tsx","doc":"Passed to NewPlaylistButton by the user's profile and playlists pages, which add the new playlist to their list through onCreated.","url":"./src/components/playlist/NewPlaylistButton.tsx/~/NewPlaylistButtonProps.html","deprecated":false},{"id":"namespace_newplaylistbuttonprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"NewPlaylistButtonProps.onCreated","file":"src/components/playlist/NewPlaylistButton.tsx","doc":"","url":"./src/components/playlist/NewPlaylistButton.tsx/~/NewPlaylistButtonProps.onCreated.html","deprecated":false},{"id":"namespace_newplaylistbuttonprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"NewPlaylistButtonProps.toggleLabel","file":"src/components/playlist/NewPlaylistButton.tsx","doc":"\"+ New playlist\" by default.","url":"./src/components/playlist/NewPlaylistButton.tsx/~/NewPlaylistButtonProps.toggleLabel.html","deprecated":false},{"id":"namespace_newplaylistbuttonprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"NewPlaylistButtonProps.toggleClassName","file":"src/components/playlist/NewPlaylistButton.tsx","doc":"","url":"./src/components/playlist/NewPlaylistButton.tsx/~/NewPlaylistButtonProps.toggleClassName.html","deprecated":false},{"id":"namespace_newplaylistbutton","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"NewPlaylistButton","file":"src/components/playlist/NewPlaylistButton.tsx","doc":"Renders a button that opens PlaylistCreateForm in a modal, which closes once the playlist is created.","url":"./src/components/playlist/NewPlaylistButton.tsx/~/NewPlaylistButton.html","deprecated":false},{"id":"namespace_playlistcardprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PlaylistCardProps","file":"src/components/playlist/PlaylistCard.tsx","doc":"Passed to PlaylistCard by each list of playlists.","url":"./src/components/playlist/PlaylistCard.tsx/~/PlaylistCardProps.html","deprecated":false},{"id":"namespace_playlistcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistCardProps.playlist","file":"src/components/playlist/PlaylistCard.tsx","doc":"","url":"./src/components/playlist/PlaylistCard.tsx/~/PlaylistCardProps.playlist.html","deprecated":false},{"id":"namespace_playlistcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistCardProps.onDelete","file":"src/components/playlist/PlaylistCard.tsx","doc":"Shows a delete button, which calls it. The owner's playlists pages pass one that asks for confirmation first.","url":"./src/components/playlist/PlaylistCard.tsx/~/PlaylistCardProps.onDelete.html","deprecated":false},{"id":"namespace_playlistcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistCardProps.isOwner","file":"src/components/playlist/PlaylistCard.tsx","doc":"Hides the owner link and the unread dot.","url":"./src/components/playlist/PlaylistCard.tsx/~/PlaylistCardProps.isOwner.html","deprecated":false},{"id":"namespace_playlistcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistCardProps.privateBadgeOnly","file":"src/components/playlist/PlaylistCard.tsx","doc":"Used by dump pages to display \"In collections\" lists. Prevents the visibility badge from showing, except to the owner of a private playlist: public badges on every card there would say nothing.","url":"./src/components/playlist/PlaylistCard.tsx/~/PlaylistCardProps.privateBadgeOnly.html","deprecated":false},{"id":"namespace_playlistcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistCardProps.grid","file":"src/components/playlist/PlaylistCard.tsx","doc":"Set for a tile of the playlists page's grid, whose cover is larger.","url":"./src/components/playlist/PlaylistCard.tsx/~/PlaylistCardProps.grid.html","deprecated":false},{"id":"namespace_playlistcard","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"PlaylistCard","file":"src/components/playlist/PlaylistCard.tsx","doc":"Renders a playlist as a card that opens the playlist when clicked, in a new tab on a middle click (useCardLink), with its cover, or a tile of its own colour without one, the playlist categories it is filed under and when it last took a dump. Another user's recent playlist shows an unread dot until it is opened on this device. The card is an <li>, for a <ul>, whose class lays it out: a row in a .dump-feed, a tile in a .playlist-grid.","url":"./src/components/playlist/PlaylistCard.tsx/~/PlaylistCard.html","deprecated":false},{"id":"namespace_playlistcardlistprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PlaylistCardListProps","file":"src/components/playlist/PlaylistCardList.tsx","doc":"Passed to PlaylistCardList by every list of playlist cards.","url":"./src/components/playlist/PlaylistCardList.tsx/~/PlaylistCardListProps.html","deprecated":false},{"id":"namespace_playlistcardlistprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistCardListProps.playlists","file":"src/components/playlist/PlaylistCardList.tsx","doc":"","url":"./src/components/playlist/PlaylistCardList.tsx/~/PlaylistCardListProps.playlists.html","deprecated":false},{"id":"namespace_playlistcardlistprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistCardListProps.onDelete","file":"src/components/playlist/PlaylistCardList.tsx","doc":"Given, each card shows a delete button, which calls it.","url":"./src/components/playlist/PlaylistCardList.tsx/~/PlaylistCardListProps.onDelete.html","deprecated":false},{"id":"namespace_playlistcardlistprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistCardListProps.privateBadgeOnly","file":"src/components/playlist/PlaylistCardList.tsx","doc":"Passed to each PlaylistCard.","url":"./src/components/playlist/PlaylistCardList.tsx/~/PlaylistCardListProps.privateBadgeOnly.html","deprecated":false},{"id":"namespace_playlistcardlistprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistCardListProps.grid","file":"src/components/playlist/PlaylistCardList.tsx","doc":"Lays the cards out as tiles, cover first, several to a row, for a page that is a list of playlists and nothing else: the playlists page.","url":"./src/components/playlist/PlaylistCardList.tsx/~/PlaylistCardListProps.grid.html","deprecated":false},{"id":"namespace_playlistcardlist","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"PlaylistCardList","file":"src/components/playlist/PlaylistCardList.tsx","doc":"Renders playlists as a .dump-feed of PlaylistCard, one to a row, or as a .playlist-grid of them, a card being its owner's when the playlist is the signed-in user's.","url":"./src/components/playlist/PlaylistCardList.tsx/~/PlaylistCardList.html","deprecated":false},{"id":"namespace_playlistcreateformprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PlaylistCreateFormProps","file":"src/components/playlist/PlaylistCreateForm.tsx","doc":"Passed to PlaylistCreateForm by NewPlaylistButton and PlaylistMembershipPanel.","url":"./src/components/playlist/PlaylistCreateForm.tsx/~/PlaylistCreateFormProps.html","deprecated":false},{"id":"namespace_playlistcreateformprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistCreateFormProps.dumpId","file":"src/components/playlist/PlaylistCreateForm.tsx","doc":"Added to the new playlist, which the submit button says.","url":"./src/components/playlist/PlaylistCreateForm.tsx/~/PlaylistCreateFormProps.dumpId.html","deprecated":false},{"id":"namespace_playlistcreateformprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistCreateFormProps.onCreated","file":"src/components/playlist/PlaylistCreateForm.tsx","doc":"hasDump tells whether dumpId made it into the new playlist.","url":"./src/components/playlist/PlaylistCreateForm.tsx/~/PlaylistCreateFormProps.onCreated.html","deprecated":false},{"id":"namespace_playlistcreateformprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistCreateFormProps.onCancel","file":"src/components/playlist/PlaylistCreateForm.tsx","doc":"","url":"./src/components/playlist/PlaylistCreateForm.tsx/~/PlaylistCreateFormProps.onCancel.html","deprecated":false},{"id":"namespace_playlistcreateformprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistCreateFormProps.className","file":"src/components/playlist/PlaylistCreateForm.tsx","doc":"","url":"./src/components/playlist/PlaylistCreateForm.tsx/~/PlaylistCreateFormProps.className.html","deprecated":false},{"id":"namespace_playlistcreateform","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"PlaylistCreateForm","file":"src/components/playlist/PlaylistCreateForm.tsx","doc":"Renders the form that creates a playlist with POST /api/playlists, then adds dumpId to it when given. The playlist exists even if adding the dump fails, so onCreated runs either way and says which.","url":"./src/components/playlist/PlaylistCreateForm.tsx/~/PlaylistCreateForm.html","deprecated":false},{"id":"namespace_playlistdumplistprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PlaylistDumpListProps","file":"src/components/playlist/PlaylistDumpList.tsx","doc":"Passed to PlaylistDumpList by PlaylistDetail, from usePlaylist. The calls are given only to those who may edit the playlist.","url":"./src/components/playlist/PlaylistDumpList.tsx/~/PlaylistDumpListProps.html","deprecated":false},{"id":"namespace_playlistdumplistprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistDumpListProps.dumps","file":"src/components/playlist/PlaylistDumpList.tsx","doc":"","url":"./src/components/playlist/PlaylistDumpList.tsx/~/PlaylistDumpListProps.dumps.html","deprecated":false},{"id":"namespace_playlistdumplistprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistDumpListProps.fading","file":"src/components/playlist/PlaylistDumpList.tsx","doc":"","url":"./src/components/playlist/PlaylistDumpList.tsx/~/PlaylistDumpListProps.fading.html","deprecated":false},{"id":"namespace_playlistdumplistprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistDumpListProps.onRemove","file":"src/components/playlist/PlaylistDumpList.tsx","doc":"","url":"./src/components/playlist/PlaylistDumpList.tsx/~/PlaylistDumpListProps.onRemove.html","deprecated":false},{"id":"namespace_playlistdumplistprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistDumpListProps.onUndoRemove","file":"src/components/playlist/PlaylistDumpList.tsx","doc":"","url":"./src/components/playlist/PlaylistDumpList.tsx/~/PlaylistDumpListProps.onUndoRemove.html","deprecated":false},{"id":"namespace_playlistdumplistprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistDumpListProps.onMove","file":"src/components/playlist/PlaylistDumpList.tsx","doc":"Counts only the dumps not fading, which alone can be dragged.","url":"./src/components/playlist/PlaylistDumpList.tsx/~/PlaylistDumpListProps.onMove.html","deprecated":false},{"id":"namespace_playlistdumplistprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistDumpListProps.onMoved","file":"src/components/playlist/PlaylistDumpList.tsx","doc":"Called as a drag ends, to save the order onMove left.","url":"./src/components/playlist/PlaylistDumpList.tsx/~/PlaylistDumpListProps.onMoved.html","deprecated":false},{"id":"namespace_playlistdumplist","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"PlaylistDumpList","file":"src/components/playlist/PlaylistDumpList.tsx","doc":"Renders the dumps, or a line saying there are none. With the calls, each dump not fading has a drag handle and a remove button, and one fading an \"Undo\" during its cooldown.","url":"./src/components/playlist/PlaylistDumpList.tsx/~/PlaylistDumpList.html","deprecated":false},{"id":"namespace_playlisteditformprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PlaylistEditFormProps","file":"src/components/playlist/PlaylistEditForm.tsx","doc":"Passed to PlaylistEditForm by PlaylistDetail.","url":"./src/components/playlist/PlaylistEditForm.tsx/~/PlaylistEditFormProps.html","deprecated":false},{"id":"namespace_playlisteditformprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistEditFormProps.playlist","file":"src/components/playlist/PlaylistEditForm.tsx","doc":"","url":"./src/components/playlist/PlaylistEditForm.tsx/~/PlaylistEditFormProps.playlist.html","deprecated":false},{"id":"namespace_playlisteditformprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistEditFormProps.onCancel","file":"src/components/playlist/PlaylistEditForm.tsx","doc":"","url":"./src/components/playlist/PlaylistEditForm.tsx/~/PlaylistEditFormProps.onCancel.html","deprecated":false},{"id":"namespace_playlisteditformprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistEditFormProps.onRequestDelete","file":"src/components/playlist/PlaylistEditForm.tsx","doc":"Opens the page's confirmation, which deletes the playlist.","url":"./src/components/playlist/PlaylistEditForm.tsx/~/PlaylistEditFormProps.onRequestDelete.html","deprecated":false},{"id":"namespace_playlisteditformprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistEditFormProps.onSaved","file":"src/components/playlist/PlaylistEditForm.tsx","doc":"Called with the playlist as the server now has it.","url":"./src/components/playlist/PlaylistEditForm.tsx/~/PlaylistEditFormProps.onSaved.html","deprecated":false},{"id":"namespace_playlisteditform","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"PlaylistEditForm","file":"src/components/playlist/PlaylistEditForm.tsx","doc":"Renders the form that edits the playlist, in place of the page's header. It saves the details with PUT /api/playlists/:playlistId, sending only the title, slug, description and categories that changed, then a new cover, if one was picked, with PUT /api/playlists/:playlistId/cover.","url":"./src/components/playlist/PlaylistEditForm.tsx/~/PlaylistEditForm.html","deprecated":false},{"id":"namespace_playlistheaderprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PlaylistHeaderProps","file":"src/components/playlist/PlaylistHeader.tsx","doc":"Passed to PlaylistHeader by PlaylistDetail.","url":"./src/components/playlist/PlaylistHeader.tsx/~/PlaylistHeaderProps.html","deprecated":false},{"id":"namespace_playlistheaderprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistHeaderProps.playlist","file":"src/components/playlist/PlaylistHeader.tsx","doc":"","url":"./src/components/playlist/PlaylistHeader.tsx/~/PlaylistHeaderProps.playlist.html","deprecated":false},{"id":"namespace_playlistheaderprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistHeaderProps.onEdit","file":"src/components/playlist/PlaylistHeader.tsx","doc":"Given to those who may edit it, with onSaved: it adds an \"Edit\" button, which opens PlaylistEditForm.","url":"./src/components/playlist/PlaylistHeader.tsx/~/PlaylistHeaderProps.onEdit.html","deprecated":false},{"id":"namespace_playlistheaderprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistHeaderProps.onSaved","file":"src/components/playlist/PlaylistHeader.tsx","doc":"Called with the playlist as the server has it once its title or description is edited in place, which it lets its editors do.","url":"./src/components/playlist/PlaylistHeader.tsx/~/PlaylistHeaderProps.onSaved.html","deprecated":false},{"id":"namespace_playlistheader","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"PlaylistHeader","file":"src/components/playlist/PlaylistHeader.tsx","doc":"Renders the playlist's details, with a follow button for anyone but its owner. Its editors change the title and the description in place, saved to PUT /api/playlists/:playlistId, and the rest in PlaylistEditForm, which takes the header's place while it is open.","url":"./src/components/playlist/PlaylistHeader.tsx/~/PlaylistHeader.html","deprecated":false},{"id":"namespace_playlistmembershippanelprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PlaylistMembershipPanelProps","file":"src/components/playlist/PlaylistMembershipPanel.tsx","doc":"Passed to PlaylistMembershipPanel by AddToPlaylistModal and the dump form, which fetch the memberships and call the server on a toggle. The panel only shows them.","url":"./src/components/playlist/PlaylistMembershipPanel.tsx/~/PlaylistMembershipPanelProps.html","deprecated":false},{"id":"namespace_playlistmembershippanelprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistMembershipPanelProps.dumpId","file":"src/components/playlist/PlaylistMembershipPanel.tsx","doc":"","url":"./src/components/playlist/PlaylistMembershipPanel.tsx/~/PlaylistMembershipPanelProps.dumpId.html","deprecated":false},{"id":"namespace_playlistmembershippanelprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistMembershipPanelProps.memberships","file":"src/components/playlist/PlaylistMembershipPanel.tsx","doc":"","url":"./src/components/playlist/PlaylistMembershipPanel.tsx/~/PlaylistMembershipPanelProps.memberships.html","deprecated":false},{"id":"namespace_playlistmembershippanelprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistMembershipPanelProps.loading","file":"src/components/playlist/PlaylistMembershipPanel.tsx","doc":"","url":"./src/components/playlist/PlaylistMembershipPanel.tsx/~/PlaylistMembershipPanelProps.loading.html","deprecated":false},{"id":"namespace_playlistmembershippanelprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistMembershipPanelProps.onToggle","file":"src/components/playlist/PlaylistMembershipPanel.tsx","doc":"","url":"./src/components/playlist/PlaylistMembershipPanel.tsx/~/PlaylistMembershipPanelProps.onToggle.html","deprecated":false},{"id":"namespace_playlistmembershippanelprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistMembershipPanelProps.onPlaylistCreated","file":"src/components/playlist/PlaylistMembershipPanel.tsx","doc":"Called with a playlist created from the panel, which holds the dump.","url":"./src/components/playlist/PlaylistMembershipPanel.tsx/~/PlaylistMembershipPanelProps.onPlaylistCreated.html","deprecated":false},{"id":"namespace_playlistmembershippanel","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"PlaylistMembershipPanel","file":"src/components/playlist/PlaylistMembershipPanel.tsx","doc":"Renders the playlists as checkboxes, which the keyboard toggles too, and a button that opens PlaylistCreateForm to make one holding the dump.","url":"./src/components/playlist/PlaylistMembershipPanel.tsx/~/PlaylistMembershipPanel.html","deprecated":false},{"id":"namespace_playlistsorttabsprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PlaylistSortTabsProps","file":"src/components/playlist/PlaylistSortTabs.tsx","doc":"Passed to PlaylistSortTabs by ProfilePlaylistsTab, whose tabs are PLAYLIST_SORTS, and by Playlists, whose PLAYLISTS_TABS add the viewer's own playlists for a signed-in user. Both keep the active one in their URL's query.","url":"./src/components/playlist/PlaylistSortTabs.tsx/~/PlaylistSortTabsProps.html","deprecated":false},{"id":"namespace_playlistsorttabsprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistSortTabsProps.tabs","file":"src/components/playlist/PlaylistSortTabs.tsx","doc":"The tabs offered, in order.","url":"./src/components/playlist/PlaylistSortTabs.tsx/~/PlaylistSortTabsProps.tabs.html","deprecated":false},{"id":"namespace_playlistsorttabsprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistSortTabsProps.sort","file":"src/components/playlist/PlaylistSortTabs.tsx","doc":"The active tab.","url":"./src/components/playlist/PlaylistSortTabs.tsx/~/PlaylistSortTabsProps.sort.html","deprecated":false},{"id":"namespace_playlistsorttabsprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistSortTabsProps.onChange","file":"src/components/playlist/PlaylistSortTabs.tsx","doc":"","url":"./src/components/playlist/PlaylistSortTabs.tsx/~/PlaylistSortTabsProps.onChange.html","deprecated":false},{"id":"namespace_playlistsorttabsprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistSortTabsProps.leading","file":"src/components/playlist/PlaylistSortTabs.tsx","doc":"Goes before the tabs, as the playlists page's category menu does.","url":"./src/components/playlist/PlaylistSortTabs.tsx/~/PlaylistSortTabsProps.leading.html","deprecated":false},{"id":"namespace_playlistsorttabs","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"PlaylistSortTabs","file":"src/components/playlist/PlaylistSortTabs.tsx","doc":"Renders one tab per entry of tabs, sort being the active one.","url":"./src/components/playlist/PlaylistSortTabs.tsx/~/PlaylistSortTabs.html","deprecated":false},{"id":"namespace_changepasswordmodalprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ChangePasswordModalProps","file":"src/components/profile/ChangePasswordModal.tsx","doc":"Passed to ChangePasswordModal by UserPublicProfile.","url":"./src/components/profile/ChangePasswordModal.tsx/~/ChangePasswordModalProps.html","deprecated":false},{"id":"namespace_changepasswordmodalprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChangePasswordModalProps.onClose","file":"src/components/profile/ChangePasswordModal.tsx","doc":"","url":"./src/components/profile/ChangePasswordModal.tsx/~/ChangePasswordModalProps.onClose.html","deprecated":false},{"id":"namespace_changepasswordmodal","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"ChangePasswordModal","file":"src/components/profile/ChangePasswordModal.tsx","doc":"Renders the form that changes the user's password, given the current one. The change signs out every other session, in every browser.","url":"./src/components/profile/ChangePasswordModal.tsx/~/ChangePasswordModal.html","deprecated":false},{"id":"namespace_profiledescriptionprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ProfileDescriptionProps","file":"src/components/profile/ProfileDescription.tsx","doc":"Passed to ProfileDescription by UserPublicProfile.","url":"./src/components/profile/ProfileDescription.tsx/~/ProfileDescriptionProps.html","deprecated":false},{"id":"namespace_profiledescriptionprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ProfileDescriptionProps.description","file":"src/components/profile/ProfileDescription.tsx","doc":"","url":"./src/components/profile/ProfileDescription.tsx/~/ProfileDescriptionProps.description.html","deprecated":false},{"id":"namespace_profiledescriptionprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ProfileDescriptionProps.isOwnProfile","file":"src/components/profile/ProfileDescription.tsx","doc":"","url":"./src/components/profile/ProfileDescription.tsx/~/ProfileDescriptionProps.isOwnProfile.html","deprecated":false},{"id":"namespace_profiledescriptionprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ProfileDescriptionProps.onSaved","file":"src/components/profile/ProfileDescription.tsx","doc":"Called with the saved description, undefined once cleared.","url":"./src/components/profile/ProfileDescription.tsx/~/ProfileDescriptionProps.onSaved.html","deprecated":false},{"id":"namespace_profiledescription","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"ProfileDescription","file":"src/components/profile/ProfileDescription.tsx","doc":"Renders the description in Markdown, or nothing when there is none. On their own profile, users get a \"Who am I?\" placeholder instead, and edit it in place, saved to PATCH /api/me. Other browsers see the change through the socket's user_updated event.","url":"./src/components/profile/ProfileDescription.tsx/~/ProfileDescription.html","deprecated":false},{"id":"namespace_profiledumpstabprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ProfileDumpsTabProps","file":"src/components/profile/ProfileDumpsTab.tsx","doc":"Passed to ProfileDumpsTab by UserPublicProfile.","url":"./src/components/profile/ProfileDumpsTab.tsx/~/ProfileDumpsTabProps.html","deprecated":false},{"id":"namespace_profiledumpstabprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ProfileDumpsTabProps.user","file":"src/components/profile/ProfileDumpsTab.tsx","doc":"","url":"./src/components/profile/ProfileDumpsTab.tsx/~/ProfileDumpsTabProps.user.html","deprecated":false},{"id":"namespace_profiledumpstabprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ProfileDumpsTabProps.list","file":"src/components/profile/ProfileDumpsTab.tsx","doc":"","url":"./src/components/profile/ProfileDumpsTab.tsx/~/ProfileDumpsTabProps.list.html","deprecated":false},{"id":"namespace_profiledumpstabprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ProfileDumpsTabProps.isOwnProfile","file":"src/components/profile/ProfileDumpsTab.tsx","doc":"","url":"./src/components/profile/ProfileDumpsTab.tsx/~/ProfileDumpsTabProps.isOwnProfile.html","deprecated":false},{"id":"namespace_profiledumpstab","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"ProfileDumpsTab","file":"src/components/profile/ProfileDumpsTab.tsx","doc":"Renders the list, with the category menu in its title row; the category picked is the URL's ?category=, which switching to the other list keeps and to any other tab drops. The owner's own dumps get a \"New dump\" button.","url":"./src/components/profile/ProfileDumpsTab.tsx/~/ProfileDumpsTab.html","deprecated":false},{"id":"namespace_profilefollowtabprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ProfileFollowTabProps","file":"src/components/profile/ProfileFollowTab.tsx","doc":"Passed to ProfileFollowTab by UserPublicProfile.","url":"./src/components/profile/ProfileFollowTab.tsx/~/ProfileFollowTabProps.html","deprecated":false},{"id":"namespace_profilefollowtabprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ProfileFollowTabProps.user","file":"src/components/profile/ProfileFollowTab.tsx","doc":"","url":"./src/components/profile/ProfileFollowTab.tsx/~/ProfileFollowTabProps.user.html","deprecated":false},{"id":"namespace_profilefollowtabprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ProfileFollowTabProps.view","file":"src/components/profile/ProfileFollowTab.tsx","doc":"The view the path names, after /follow.","url":"./src/components/profile/ProfileFollowTab.tsx/~/ProfileFollowTabProps.view.html","deprecated":false},{"id":"namespace_profilefollowtab","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"ProfileFollowTab","file":"src/components/profile/ProfileFollowTab.tsx","doc":"Renders the two views under a row of tabs that switch between their paths, each view loading its list when first shown.","url":"./src/components/profile/ProfileFollowTab.tsx/~/ProfileFollowTab.html","deprecated":false},{"id":"namespace_profileheaderprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ProfileHeaderProps","file":"src/components/profile/ProfileHeader.tsx","doc":"Passed to ProfileHeader by UserPublicProfile, once loaded.","url":"./src/components/profile/ProfileHeader.tsx/~/ProfileHeaderProps.html","deprecated":false},{"id":"namespace_profileheaderprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ProfileHeaderProps.user","file":"src/components/profile/ProfileHeader.tsx","doc":"","url":"./src/components/profile/ProfileHeader.tsx/~/ProfileHeaderProps.user.html","deprecated":false},{"id":"namespace_profileheaderprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ProfileHeaderProps.isOwnProfile","file":"src/components/profile/ProfileHeader.tsx","doc":"","url":"./src/components/profile/ProfileHeader.tsx/~/ProfileHeaderProps.isOwnProfile.html","deprecated":false},{"id":"namespace_profileheaderprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ProfileHeaderProps.onUserChange","file":"src/components/profile/ProfileHeader.tsx","doc":"Called with the user as a new avatar left them.","url":"./src/components/profile/ProfileHeader.tsx/~/ProfileHeaderProps.onUserChange.html","deprecated":false},{"id":"namespace_profileheader","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"ProfileHeader","file":"src/components/profile/ProfileHeader.tsx","doc":"Renders the avatar, username, role and inviter, and for a user from another instance, a link to their profile there. Visitors get a follow button. On their own profile, users change their avatar (PUT /api/me/avatar) and email (PATCH /api/me), unless their account comes from another instance, and invite someone; their settings, the site's tools and logging out are in the header's avatar menu.","url":"./src/components/profile/ProfileHeader.tsx/~/ProfileHeader.html","deprecated":false},{"id":"namespace_profileinviteestabprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ProfileInviteesTabProps","file":"src/components/profile/ProfileInviteesTab.tsx","doc":"Passed to ProfileInviteesTab by UserPublicProfile.","url":"./src/components/profile/ProfileInviteesTab.tsx/~/ProfileInviteesTabProps.html","deprecated":false},{"id":"namespace_profileinviteestabprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ProfileInviteesTabProps.userId","file":"src/components/profile/ProfileInviteesTab.tsx","doc":"","url":"./src/components/profile/ProfileInviteesTab.tsx/~/ProfileInviteesTabProps.userId.html","deprecated":false},{"id":"namespace_profileinviteestabprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ProfileInviteesTabProps.state","file":"src/components/profile/ProfileInviteesTab.tsx","doc":"Loaded when the tab is first opened, from GET /api/users/@:username/invitees.","url":"./src/components/profile/ProfileInviteesTab.tsx/~/ProfileInviteesTabProps.state.html","deprecated":false},{"id":"namespace_profileinviteestab","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"ProfileInviteesTab","file":"src/components/profile/ProfileInviteesTab.tsx","doc":"Renders the invitees of userId as a tree.","url":"./src/components/profile/ProfileInviteesTab.tsx/~/ProfileInviteesTab.html","deprecated":false},{"id":"namespace_profilemanagetabprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ProfileManageTabProps","file":"src/components/profile/ProfileManageTab.tsx","doc":"Passed to ProfileManageTab by UserPublicProfile, which shows the tab on another user's profile to those who hold user:manage.","url":"./src/components/profile/ProfileManageTab.tsx/~/ProfileManageTabProps.html","deprecated":false},{"id":"namespace_profilemanagetabprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ProfileManageTabProps.user","file":"src/components/profile/ProfileManageTab.tsx","doc":"","url":"./src/components/profile/ProfileManageTab.tsx/~/ProfileManageTabProps.user.html","deprecated":false},{"id":"namespace_profilemanagetabprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ProfileManageTabProps.onUserSaved","file":"src/components/profile/ProfileManageTab.tsx","doc":"Called with the user as the server left them.","url":"./src/components/profile/ProfileManageTab.tsx/~/ProfileManageTabProps.onUserSaved.html","deprecated":false},{"id":"namespace_profilemanagetab","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"ProfileManageTab","file":"src/components/profile/ProfileManageTab.tsx","doc":"Renders the user's role and name. A rename here has no rate limit, and the profile's URL then takes the new name. A user from another instance is named there, so their name is only shown.","url":"./src/components/profile/ProfileManageTab.tsx/~/ProfileManageTab.html","deprecated":false},{"id":"namespace_profileoverviewtabprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ProfileOverviewTabProps","file":"src/components/profile/ProfileOverviewTab.tsx","doc":"Passed to ProfileOverviewTab by UserPublicProfile.","url":"./src/components/profile/ProfileOverviewTab.tsx/~/ProfileOverviewTabProps.html","deprecated":false},{"id":"namespace_profileoverviewtabprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ProfileOverviewTabProps.user","file":"src/components/profile/ProfileOverviewTab.tsx","doc":"","url":"./src/components/profile/ProfileOverviewTab.tsx/~/ProfileOverviewTabProps.user.html","deprecated":false},{"id":"namespace_profileoverviewtabprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ProfileOverviewTabProps.isOwnProfile","file":"src/components/profile/ProfileOverviewTab.tsx","doc":"","url":"./src/components/profile/ProfileOverviewTab.tsx/~/ProfileOverviewTabProps.isOwnProfile.html","deprecated":false},{"id":"namespace_profileoverviewtab","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"ProfileOverviewTab","file":"src/components/profile/ProfileOverviewTab.tsx","doc":"Renders the first page of both lists, from useUserDumpFeed, each linking to its tab. The owner also gets a \"New dump\" button.","url":"./src/components/profile/ProfileOverviewTab.tsx/~/ProfileOverviewTab.html","deprecated":false},{"id":"namespace_profileownactions","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"ProfileOwnActions","file":"src/components/profile/ProfileOwnActions.tsx","doc":"Renders the \"Invite someone\" button, which opens a panel with an invite link. Each opening of the panel creates a new single-use link, for /register.","url":"./src/components/profile/ProfileOwnActions.tsx/~/ProfileOwnActions.html","deprecated":false},{"id":"namespace_profileplayliststabprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ProfilePlaylistsTabProps","file":"src/components/profile/ProfilePlaylistsTab.tsx","doc":"Passed to ProfilePlaylistsTab by UserPublicProfile.","url":"./src/components/profile/ProfilePlaylistsTab.tsx/~/ProfilePlaylistsTabProps.html","deprecated":false},{"id":"namespace_profileplayliststabprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ProfilePlaylistsTabProps.user","file":"src/components/profile/ProfilePlaylistsTab.tsx","doc":"","url":"./src/components/profile/ProfilePlaylistsTab.tsx/~/ProfilePlaylistsTabProps.user.html","deprecated":false},{"id":"namespace_profileplayliststabprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ProfilePlaylistsTabProps.isOwnProfile","file":"src/components/profile/ProfilePlaylistsTab.tsx","doc":"","url":"./src/components/profile/ProfilePlaylistsTab.tsx/~/ProfilePlaylistsTabProps.isOwnProfile.html","deprecated":false},{"id":"namespace_profileplayliststab","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"ProfilePlaylistsTab","file":"src/components/profile/ProfilePlaylistsTab.tsx","doc":"Renders the tab's list for the playlist category the URL's ?category= picks, or every playlist without one, in the order its ?sort= names. Each category's list in each order is another, which the tab mounts afresh.","url":"./src/components/profile/ProfilePlaylistsTab.tsx/~/ProfilePlaylistsTab.html","deprecated":false},{"id":"namespace_profilesectionprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ProfileSectionProps","file":"src/components/profile/ProfileSection.tsx","doc":"Passed to ProfileSection by the profile's tabs, and by the settings and manage pages.","url":"./src/components/profile/ProfileSection.tsx/~/ProfileSectionProps.html","deprecated":false},{"id":"namespace_profilesectionprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ProfileSectionProps.title","file":"src/components/profile/ProfileSection.tsx","doc":"","url":"./src/components/profile/ProfileSection.tsx/~/ProfileSectionProps.title.html","deprecated":false},{"id":"namespace_profilesectionprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ProfileSectionProps.actions","file":"src/components/profile/ProfileSection.tsx","doc":"They go at the end of the title row.","url":"./src/components/profile/ProfileSection.tsx/~/ProfileSectionProps.actions.html","deprecated":false},{"id":"namespace_profilesectionprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ProfileSectionProps.viewAllHref","file":"src/components/profile/ProfileSection.tsx","doc":"It links to the page with the whole list, of which the section shows the first page. The profile leaves it out while the list is empty.","url":"./src/components/profile/ProfileSection.tsx/~/ProfileSectionProps.viewAllHref.html","deprecated":false},{"id":"namespace_profilesectionprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ProfileSectionProps.children","file":"src/components/profile/ProfileSection.tsx","doc":"","url":"./src/components/profile/ProfileSection.tsx/~/ProfileSectionProps.children.html","deprecated":false},{"id":"namespace_profilesection","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"ProfileSection","file":"src/components/profile/ProfileSection.tsx","doc":"Renders a .profile-section: its title row, children, then a \"View all →\" link to viewAllHref.","url":"./src/components/profile/ProfileSection.tsx/~/ProfileSection.html","deprecated":false},{"id":"namespace_rolechip","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"RoleChip","file":"src/components/profile/RoleSwitcher.tsx","doc":"Renders the role badge next to the username in ProfileHeader, for moderators and admins only.","url":"./src/components/profile/RoleSwitcher.tsx/~/RoleChip.html","deprecated":false},{"id":"namespace_roleswitcherprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"RoleSwitcherProps","file":"src/components/profile/RoleSwitcher.tsx","doc":"Passed to RoleSwitcher by ProfileManageTab, which shows it only to those who hold user:manage, on another user's profile.","url":"./src/components/profile/RoleSwitcher.tsx/~/RoleSwitcherProps.html","deprecated":false},{"id":"namespace_roleswitcherprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RoleSwitcherProps.userId","file":"src/components/profile/RoleSwitcher.tsx","doc":"","url":"./src/components/profile/RoleSwitcher.tsx/~/RoleSwitcherProps.userId.html","deprecated":false},{"id":"namespace_roleswitcherprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RoleSwitcherProps.currentRole","file":"src/components/profile/RoleSwitcher.tsx","doc":"","url":"./src/components/profile/RoleSwitcher.tsx/~/RoleSwitcherProps.currentRole.html","deprecated":false},{"id":"namespace_roleswitcherprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RoleSwitcherProps.onSaved","file":"src/components/profile/RoleSwitcher.tsx","doc":"Called with the role the server kept.","url":"./src/components/profile/RoleSwitcher.tsx/~/RoleSwitcherProps.onSaved.html","deprecated":false},{"id":"namespace_roleswitcher","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"RoleSwitcher","file":"src/components/profile/RoleSwitcher.tsx","doc":"Renders the user's role as a Segmented whose clicks save it to PATCH /api/users/:id/role, which checks the permission again.","url":"./src/components/profile/RoleSwitcher.tsx/~/RoleSwitcher.html","deprecated":false},{"id":"namespace_settingrowprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"SettingRowProps","file":"src/components/profile/SettingRow.tsx","doc":"Passed to SettingRow by Settings, ProfileManageTab and RoleSwitcher.","url":"./src/components/profile/SettingRow.tsx/~/SettingRowProps.html","deprecated":false},{"id":"namespace_settingrowprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SettingRowProps.label","file":"src/components/profile/SettingRow.tsx","doc":"","url":"./src/components/profile/SettingRow.tsx/~/SettingRowProps.label.html","deprecated":false},{"id":"namespace_settingrowprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SettingRowProps.children","file":"src/components/profile/SettingRow.tsx","doc":"It is the row's control, usually a Segmented.","url":"./src/components/profile/SettingRow.tsx/~/SettingRowProps.children.html","deprecated":false},{"id":"namespace_settingrow","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"SettingRow","file":"src/components/profile/SettingRow.tsx","doc":"Renders label beside children, as a row of the .profile-appearance-grid its caller wraps the rows in.","url":"./src/components/profile/SettingRow.tsx/~/SettingRow.html","deprecated":false},{"id":"namespace_usernamefieldprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UsernameFieldProps","file":"src/components/profile/UsernameField.tsx","doc":"Passed to UsernameField by ProfileManageTab.","url":"./src/components/profile/UsernameField.tsx/~/UsernameFieldProps.html","deprecated":false},{"id":"namespace_usernamefieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UsernameFieldProps.username","file":"src/components/profile/UsernameField.tsx","doc":"","url":"./src/components/profile/UsernameField.tsx/~/UsernameFieldProps.username.html","deprecated":false},{"id":"namespace_usernamefieldprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UsernameFieldProps.save","file":"src/components/profile/UsernameField.tsx","doc":"Sends the new name to PATCH /api/users/:key/username, and resolves to the name the server kept. A refusal rejects with its message, which the field shows.","url":"./src/components/profile/UsernameField.tsx/~/UsernameFieldProps.save.html","deprecated":false},{"id":"namespace_usernamefield","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"UsernameField","file":"src/components/profile/UsernameField.tsx","doc":"Renders the name in a text input with a \"Rename\" button, which is enabled once the name differs.","url":"./src/components/profile/UsernameField.tsx/~/UsernameField.html","deprecated":false},{"id":"namespace_avatarprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"AvatarProps","file":"src/components/shared/Avatar.tsx","doc":"Passed to Avatar from whatever data the caller has on the user, which may be stale: a live override from AvatarOverrideContext wins over hasAvatar and version.","url":"./src/components/shared/Avatar.tsx/~/AvatarProps.html","deprecated":false},{"id":"namespace_avatarprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AvatarProps.userId","file":"src/components/shared/Avatar.tsx","doc":"","url":"./src/components/shared/Avatar.tsx/~/AvatarProps.userId.html","deprecated":false},{"id":"namespace_avatarprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AvatarProps.username","file":"src/components/shared/Avatar.tsx","doc":"","url":"./src/components/shared/Avatar.tsx/~/AvatarProps.username.html","deprecated":false},{"id":"namespace_avatarprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AvatarProps.hasAvatar","file":"src/components/shared/Avatar.tsx","doc":"","url":"./src/components/shared/Avatar.tsx/~/AvatarProps.hasAvatar.html","deprecated":false},{"id":"namespace_avatarprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AvatarProps.size","file":"src/components/shared/Avatar.tsx","doc":"Sets the side, in pixels.","url":"./src/components/shared/Avatar.tsx/~/AvatarProps.size.html","deprecated":false},{"id":"namespace_avatarprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AvatarProps.version","file":"src/components/shared/Avatar.tsx","doc":"Added to the URL so that a changed avatar isn't served from cache.","url":"./src/components/shared/Avatar.tsx/~/AvatarProps.version.html","deprecated":false},{"id":"namespace_avatar","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"Avatar","file":"src/components/shared/Avatar.tsx","doc":"Renders the image from GET /api/users/:userId/avatar, scaled by the server to the size it is shown at, or the user's initial when they have none or it fails to load. An avatar added, changed or removed since the caller's data was fetched shows at once, through the user_updated messages that WSProvider puts in AvatarOverrideContext.","url":"./src/components/shared/Avatar.tsx/~/Avatar.html","deprecated":false},{"id":"namespace_confirmmodalprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ConfirmModalProps","file":"src/components/shared/ConfirmModal.tsx","doc":"Passed to ConfirmModal by the component that shows it. The caller decides when it shows and hides it, on either callback.","url":"./src/components/shared/ConfirmModal.tsx/~/ConfirmModalProps.html","deprecated":false},{"id":"namespace_confirmmodalprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ConfirmModalProps.message","file":"src/components/shared/ConfirmModal.tsx","doc":"","url":"./src/components/shared/ConfirmModal.tsx/~/ConfirmModalProps.message.html","deprecated":false},{"id":"namespace_confirmmodalprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ConfirmModalProps.confirmLabel","file":"src/components/shared/ConfirmModal.tsx","doc":"Replaces the \"Delete\" label.","url":"./src/components/shared/ConfirmModal.tsx/~/ConfirmModalProps.confirmLabel.html","deprecated":false},{"id":"namespace_confirmmodalprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ConfirmModalProps.onConfirm","file":"src/components/shared/ConfirmModal.tsx","doc":"","url":"./src/components/shared/ConfirmModal.tsx/~/ConfirmModalProps.onConfirm.html","deprecated":false},{"id":"namespace_confirmmodalprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ConfirmModalProps.onCancel","file":"src/components/shared/ConfirmModal.tsx","doc":"Called on Cancel, Escape or a click on the backdrop.","url":"./src/components/shared/ConfirmModal.tsx/~/ConfirmModalProps.onCancel.html","deprecated":false},{"id":"namespace_confirmmodal","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"ConfirmModal","file":"src/components/shared/ConfirmModal.tsx","doc":"Renders the dialog in a portal over the page, and locks the page's scroll. Escape closes only the confirmation, even over a Modal.","url":"./src/components/shared/ConfirmModal.tsx/~/ConfirmModal.html","deprecated":false},{"id":"namespace_errorcardprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ErrorCardProps","file":"src/components/shared/ErrorCard.tsx","doc":"Passed to ErrorCard by a page or a form. The message usually comes from friendlyFetchError.","url":"./src/components/shared/ErrorCard.tsx/~/ErrorCardProps.html","deprecated":false},{"id":"namespace_errorcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ErrorCardProps.title","file":"src/components/shared/ErrorCard.tsx","doc":"Says what failed.","url":"./src/components/shared/ErrorCard.tsx/~/ErrorCardProps.title.html","deprecated":false},{"id":"namespace_errorcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ErrorCardProps.message","file":"src/components/shared/ErrorCard.tsx","doc":"","url":"./src/components/shared/ErrorCard.tsx/~/ErrorCardProps.message.html","deprecated":false},{"id":"namespace_errorcardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ErrorCardProps.actions","file":"src/components/shared/ErrorCard.tsx","doc":"Buttons shown under the card, such as \"Retry\".","url":"./src/components/shared/ErrorCard.tsx/~/ErrorCardProps.actions.html","deprecated":false},{"id":"namespace_errorcard","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"ErrorCard","file":"src/components/shared/ErrorCard.tsx","doc":"Renders the card as an ARIA alert, so a screen reader announces it when it appears.","url":"./src/components/shared/ErrorCard.tsx/~/ErrorCard.html","deprecated":false},{"id":"namespace_imagepickerprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ImagePickerProps","file":"src/components/shared/ImagePicker.tsx","doc":"Passed to ImagePicker by an edit page, which uploads the file and then passes the new image, or a local preview of it, as src.","url":"./src/components/shared/ImagePicker.tsx/~/ImagePickerProps.html","deprecated":false},{"id":"namespace_imagepickerprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ImagePickerProps.src","file":"src/components/shared/ImagePicker.tsx","doc":"Shows a \"+\" placeholder when null.","url":"./src/components/shared/ImagePicker.tsx/~/ImagePickerProps.src.html","deprecated":false},{"id":"namespace_imagepickerprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ImagePickerProps.alt","file":"src/components/shared/ImagePicker.tsx","doc":"","url":"./src/components/shared/ImagePicker.tsx/~/ImagePickerProps.alt.html","deprecated":false},{"id":"namespace_imagepickerprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ImagePickerProps.size","file":"src/components/shared/ImagePicker.tsx","doc":"Sets the side, in pixels. Without it, className sizes the picker.","url":"./src/components/shared/ImagePicker.tsx/~/ImagePickerProps.size.html","deprecated":false},{"id":"namespace_imagepickerprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ImagePickerProps.borderRadius","file":"src/components/shared/ImagePicker.tsx","doc":"In pixels when a number, or any CSS length, such as a radius token.","url":"./src/components/shared/ImagePicker.tsx/~/ImagePickerProps.borderRadius.html","deprecated":false},{"id":"namespace_imagepickerprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ImagePickerProps.onChange","file":"src/components/shared/ImagePicker.tsx","doc":"Called with the file picked. The same file can be picked again.","url":"./src/components/shared/ImagePicker.tsx/~/ImagePickerProps.onChange.html","deprecated":false},{"id":"namespace_imagepickerprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ImagePickerProps.uploading","file":"src/components/shared/ImagePicker.tsx","doc":"Disables the picker and shows \"…\" while the caller uploads.","url":"./src/components/shared/ImagePicker.tsx/~/ImagePickerProps.uploading.html","deprecated":false},{"id":"namespace_imagepickerprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ImagePickerProps.accept","file":"src/components/shared/ImagePicker.tsx","doc":"Replaces the default types, which are JPEG, PNG, GIF and WebP.","url":"./src/components/shared/ImagePicker.tsx/~/ImagePickerProps.accept.html","deprecated":false},{"id":"namespace_imagepickerprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ImagePickerProps.className","file":"src/components/shared/ImagePicker.tsx","doc":"","url":"./src/components/shared/ImagePicker.tsx/~/ImagePickerProps.className.html","deprecated":false},{"id":"namespace_imagepicker","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"ImagePicker","file":"src/components/shared/ImagePicker.tsx","doc":"Renders the image, or a placeholder, which opens the file picker on a click, Enter or Space. The picker only reads the file, and uploads nothing itself.","url":"./src/components/shared/ImagePicker.tsx/~/ImagePicker.html","deprecated":false},{"id":"namespace_liststateprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ListStateProps","file":"src/components/shared/ListState.tsx","doc":"Passed to ListState by the feeds of the index and the lists of a profile.","url":"./src/components/shared/ListState.tsx/~/ListStateProps.html","deprecated":false},{"id":"namespace_liststateprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ListStateProps.state","file":"src/components/shared/ListState.tsx","doc":"","url":"./src/components/shared/ListState.tsx/~/ListStateProps.state.html","deprecated":false},{"id":"namespace_liststateprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ListStateProps.isEmpty","file":"src/components/shared/ListState.tsx","doc":"Called only once state is loaded.","url":"./src/components/shared/ListState.tsx/~/ListStateProps.isEmpty.html","deprecated":false},{"id":"namespace_liststateprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ListStateProps.empty","file":"src/components/shared/ListState.tsx","doc":"Shown when isEmpty, usually a .empty-state or .index-status line.","url":"./src/components/shared/ListState.tsx/~/ListStateProps.empty.html","deprecated":false},{"id":"namespace_liststateprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ListStateProps.children","file":"src/components/shared/ListState.tsx","doc":"Called only once state is loaded and not empty.","url":"./src/components/shared/ListState.tsx/~/ListStateProps.children.html","deprecated":false},{"id":"namespace_liststate","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"ListState","file":"src/components/shared/ListState.tsx","doc":"Renders \"Loading…\" while state loads, its error in an ErrorCard, then empty or children. Those two are only built once loaded, so they can read the loaded fields without checking the status again.","url":"./src/components/shared/ListState.tsx/~/ListState.html","deprecated":false},{"id":"namespace_loadmorebuttonprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"LoadMoreButtonProps","file":"src/components/shared/LoadMoreButton.tsx","doc":"Passed to LoadMoreButton by the lists that load their next page on a click, which render it while there is more to load.","url":"./src/components/shared/LoadMoreButton.tsx/~/LoadMoreButtonProps.html","deprecated":false},{"id":"namespace_loadmorebuttonprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"LoadMoreButtonProps.loadingMore","file":"src/components/shared/LoadMoreButton.tsx","doc":"","url":"./src/components/shared/LoadMoreButton.tsx/~/LoadMoreButtonProps.loadingMore.html","deprecated":false},{"id":"namespace_loadmorebuttonprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"LoadMoreButtonProps.onClick","file":"src/components/shared/LoadMoreButton.tsx","doc":"","url":"./src/components/shared/LoadMoreButton.tsx/~/LoadMoreButtonProps.onClick.html","deprecated":false},{"id":"namespace_loadmorebuttonprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"LoadMoreButtonProps.className","file":"src/components/shared/LoadMoreButton.tsx","doc":"load-more-btn by default.","url":"./src/components/shared/LoadMoreButton.tsx/~/LoadMoreButtonProps.className.html","deprecated":false},{"id":"namespace_loadmorebutton","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"LoadMoreButton","file":"src/components/shared/LoadMoreButton.tsx","doc":"Renders \"Load more\", disabled and reading \"Loading…\" while it loads.","url":"./src/components/shared/LoadMoreButton.tsx/~/LoadMoreButton.html","deprecated":false},{"id":"namespace_modalprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ModalProps","file":"src/components/shared/Modal.tsx","doc":"Passed to Modal by the component that shows it, which unmounts it in onClose.","url":"./src/components/shared/Modal.tsx/~/ModalProps.html","deprecated":false},{"id":"namespace_modalprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ModalProps.title","file":"src/components/shared/Modal.tsx","doc":"","url":"./src/components/shared/Modal.tsx/~/ModalProps.title.html","deprecated":false},{"id":"namespace_modalprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ModalProps.onClose","file":"src/components/shared/Modal.tsx","doc":"","url":"./src/components/shared/Modal.tsx/~/ModalProps.onClose.html","deprecated":false},{"id":"namespace_modalprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ModalProps.children","file":"src/components/shared/Modal.tsx","doc":"","url":"./src/components/shared/Modal.tsx/~/ModalProps.children.html","deprecated":false},{"id":"namespace_modalprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ModalProps.wide","file":"src/components/shared/Modal.tsx","doc":"","url":"./src/components/shared/Modal.tsx/~/ModalProps.wide.html","deprecated":false},{"id":"namespace_modalprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ModalProps.onBeforeClose","file":"src/components/shared/Modal.tsx","doc":"Runs before a dismissal by Escape, the backdrop or the ✕. Returning false cancels it, so that a dialog holding an unsaved draft can ask first.","url":"./src/components/shared/Modal.tsx/~/ModalProps.onBeforeClose.html","deprecated":false},{"id":"namespace_modal","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"Modal","file":"src/components/shared/Modal.tsx","doc":"Renders the dialog in a portal over the page, closed by Escape, the backdrop or its ✕, and locks the page's scroll while it is open. Content that handles Escape itself must call preventDefault on it, or the dialog closes too.","url":"./src/components/shared/Modal.tsx/~/Modal.html","deprecated":false},{"id":"namespace_segmentedoption","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"SegmentedOption","file":"src/components/shared/Segmented.tsx","doc":"Passed in SegmentedProps.options. Its value is compared with === and must be unique as a string, since it keys the button.","url":"./src/components/shared/Segmented.tsx/~/SegmentedOption.html","deprecated":false},{"id":"namespace_segmentedoption","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SegmentedOption.value","file":"src/components/shared/Segmented.tsx","doc":"","url":"./src/components/shared/Segmented.tsx/~/SegmentedOption.value.html","deprecated":false},{"id":"namespace_segmentedoption","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SegmentedOption.label","file":"src/components/shared/Segmented.tsx","doc":"","url":"./src/components/shared/Segmented.tsx/~/SegmentedOption.label.html","deprecated":false},{"id":"namespace_segmentedprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"SegmentedProps","file":"src/components/shared/Segmented.tsx","doc":"Passed to Segmented by SegmentedField for a form, and by the profile's settings and role switcher, which save each click at once.","url":"./src/components/shared/Segmented.tsx/~/SegmentedProps.html","deprecated":false},{"id":"namespace_segmentedprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SegmentedProps.options","file":"src/components/shared/Segmented.tsx","doc":"","url":"./src/components/shared/Segmented.tsx/~/SegmentedProps.options.html","deprecated":false},{"id":"namespace_segmentedprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SegmentedProps.value","file":"src/components/shared/Segmented.tsx","doc":"","url":"./src/components/shared/Segmented.tsx/~/SegmentedProps.value.html","deprecated":false},{"id":"namespace_segmentedprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SegmentedProps.onChange","file":"src/components/shared/Segmented.tsx","doc":"","url":"./src/components/shared/Segmented.tsx/~/SegmentedProps.onChange.html","deprecated":false},{"id":"namespace_segmentedprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SegmentedProps.disabled","file":"src/components/shared/Segmented.tsx","doc":"","url":"./src/components/shared/Segmented.tsx/~/SegmentedProps.disabled.html","deprecated":false},{"id":"namespace_segmentedprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"SegmentedProps.className","file":"src/components/shared/Segmented.tsx","doc":"Added to visibility-toggle.","url":"./src/components/shared/Segmented.tsx/~/SegmentedProps.className.html","deprecated":false},{"id":"namespace_segmented","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"Segmented","file":"src/components/shared/Segmented.tsx","doc":"Renders the options as buttons, the one equal to value marked active.","url":"./src/components/shared/Segmented.tsx/~/Segmented.html","deprecated":false},{"id":"namespace_tab","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"Tab","file":"src/components/shared/TabBar.tsx","doc":"A tab.","url":"./src/components/shared/TabBar.tsx/~/Tab.html","deprecated":false},{"id":"namespace_tab","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Tab.key","file":"src/components/shared/TabBar.tsx","doc":"What TabBar reports when it is chosen.","url":"./src/components/shared/TabBar.tsx/~/Tab.key.html","deprecated":false},{"id":"namespace_tab","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"Tab.label","file":"src/components/shared/TabBar.tsx","doc":"What it shows.","url":"./src/components/shared/TabBar.tsx/~/Tab.label.html","deprecated":false},{"id":"namespace_tabbarprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"TabBarProps","file":"src/components/shared/TabBar.tsx","doc":"The props of TabBar.","url":"./src/components/shared/TabBar.tsx/~/TabBarProps.html","deprecated":false},{"id":"namespace_tabbarprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TabBarProps.tabs","file":"src/components/shared/TabBar.tsx","doc":"The tabs, in order.","url":"./src/components/shared/TabBar.tsx/~/TabBarProps.tabs.html","deprecated":false},{"id":"namespace_tabbarprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TabBarProps.activeTab","file":"src/components/shared/TabBar.tsx","doc":"The active tab's key.","url":"./src/components/shared/TabBar.tsx/~/TabBarProps.activeTab.html","deprecated":false},{"id":"namespace_tabbarprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TabBarProps.onChange","file":"src/components/shared/TabBar.tsx","doc":"Called with the key of the tab chosen.","url":"./src/components/shared/TabBar.tsx/~/TabBarProps.onChange.html","deprecated":false},{"id":"namespace_tabbarprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TabBarProps.className","file":"src/components/shared/TabBar.tsx","doc":"An extra class for the scroller.","url":"./src/components/shared/TabBar.tsx/~/TabBarProps.className.html","deprecated":false},{"id":"namespace_tabbarprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TabBarProps.innerClassName","file":"src/components/shared/TabBar.tsx","doc":"An extra class for the row.","url":"./src/components/shared/TabBar.tsx/~/TabBarProps.innerClassName.html","deprecated":false},{"id":"namespace_tabbarprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TabBarProps.leading","file":"src/components/shared/TabBar.tsx","doc":"Optional content rendered before the tabs (e.g. a scope selector). Sits in the same line, aligned with them, and stays where it is while they scroll: it is outside the row that scrolls, which clips them at its edge.","url":"./src/components/shared/TabBar.tsx/~/TabBarProps.leading.html","deprecated":false},{"id":"namespace_tabbar","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"TabBar","file":"src/components/shared/TabBar.tsx","doc":"Renders a row of tabs that scrolls when they don't all fit, keeping the active one in view.","url":"./src/components/shared/TabBar.tsx/~/TabBar.html","deprecated":false},{"id":"namespace_thumbnailprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ThumbnailProps","file":"src/components/shared/Thumbnail.tsx","doc":"Passed to Thumbnail by a card or the player, from the dump's rich content.","url":"./src/components/shared/Thumbnail.tsx/~/ThumbnailProps.html","deprecated":false},{"id":"namespace_thumbnailprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ThumbnailProps.src","file":"src/components/shared/Thumbnail.tsx","doc":"The image's own URL, not proxied, since the fallbacks decide when to.","url":"./src/components/shared/Thumbnail.tsx/~/ThumbnailProps.src.html","deprecated":false},{"id":"namespace_thumbnailprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ThumbnailProps.alt","file":"src/components/shared/Thumbnail.tsx","doc":"","url":"./src/components/shared/Thumbnail.tsx/~/ThumbnailProps.alt.html","deprecated":false},{"id":"namespace_thumbnailprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ThumbnailProps.className","file":"src/components/shared/Thumbnail.tsx","doc":"Applies to the image only.","url":"./src/components/shared/Thumbnail.tsx/~/ThumbnailProps.className.html","deprecated":false},{"id":"namespace_thumbnailprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ThumbnailProps.loading","file":"src/components/shared/Thumbnail.tsx","doc":"","url":"./src/components/shared/Thumbnail.tsx/~/ThumbnailProps.loading.html","deprecated":false},{"id":"namespace_thumbnailprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ThumbnailProps.sizes","file":"src/components/shared/Thumbnail.tsx","doc":"The width the image is laid out at, as imageProps takes it. An image the API serves, the site's own or a proxied one, then loads no larger than that; another site's loads as that site sends it.","url":"./src/components/shared/Thumbnail.tsx/~/ThumbnailProps.sizes.html","deprecated":false},{"id":"namespace_thumbnailprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ThumbnailProps.placeholder","file":"src/components/shared/Thumbnail.tsx","doc":"Shown when there's no src or it fails to load.","url":"./src/components/shared/Thumbnail.tsx/~/ThumbnailProps.placeholder.html","deprecated":false},{"id":"namespace_thumbnailprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ThumbnailProps.placeholderClassName","file":"src/components/shared/Thumbnail.tsx","doc":"","url":"./src/components/shared/Thumbnail.tsx/~/ThumbnailProps.placeholderClassName.html","deprecated":false},{"id":"namespace_thumbnail","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"Thumbnail","file":"src/components/shared/Thumbnail.tsx","doc":"Renders the image, and always renders something. It first loads the image with no Referer, since hotlink protection (Cloudflare's is one click) refuses a cross-site referrer but lets an empty one through. It then retries through GET /api/remote/image for the hosts that refuse an empty referrer too, and ends with the ThumbnailPlaceholder. An HTTP image goes through the proxy from the first try, to avoid mixed content.","url":"./src/components/shared/Thumbnail.tsx/~/Thumbnail.html","deprecated":false},{"id":"namespace_thumbnailplaceholderprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ThumbnailPlaceholderProps","file":"src/components/shared/ThumbnailPlaceholder.tsx","doc":"Passed to ThumbnailPlaceholder by a card, from the dump and its rich content, or through Thumbnail's placeholder.","url":"./src/components/shared/ThumbnailPlaceholder.tsx/~/ThumbnailPlaceholderProps.html","deprecated":false},{"id":"namespace_thumbnailplaceholderprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ThumbnailPlaceholderProps.url","file":"src/components/shared/ThumbnailPlaceholder.tsx","doc":"The dumped URL, whose hostname seeds the hue and the initial.","url":"./src/components/shared/ThumbnailPlaceholder.tsx/~/ThumbnailPlaceholderProps.url.html","deprecated":false},{"id":"namespace_thumbnailplaceholderprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ThumbnailPlaceholderProps.seed","file":"src/components/shared/ThumbnailPlaceholder.tsx","doc":"Seeds the hue for a file dump, which has no URL to hash.","url":"./src/components/shared/ThumbnailPlaceholder.tsx/~/ThumbnailPlaceholderProps.seed.html","deprecated":false},{"id":"namespace_thumbnailplaceholderprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ThumbnailPlaceholderProps.accentColor","file":"src/components/shared/ThumbnailPlaceholder.tsx","doc":"The dumped page's theme-color, used as the tint when it is valid.","url":"./src/components/shared/ThumbnailPlaceholder.tsx/~/ThumbnailPlaceholderProps.accentColor.html","deprecated":false},{"id":"namespace_thumbnailplaceholderprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ThumbnailPlaceholderProps.faviconUrl","file":"src/components/shared/ThumbnailPlaceholder.tsx","doc":"","url":"./src/components/shared/ThumbnailPlaceholder.tsx/~/ThumbnailPlaceholderProps.faviconUrl.html","deprecated":false},{"id":"namespace_thumbnailplaceholderprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ThumbnailPlaceholderProps.siteName","file":"src/components/shared/ThumbnailPlaceholder.tsx","doc":"Gives the initial ahead of the hostname.","url":"./src/components/shared/ThumbnailPlaceholder.tsx/~/ThumbnailPlaceholderProps.siteName.html","deprecated":false},{"id":"namespace_thumbnailplaceholderprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ThumbnailPlaceholderProps.glyph","file":"src/components/shared/ThumbnailPlaceholder.tsx","doc":"Replaces the initial, since a file dump says more with 🎬 than with \"T\".","url":"./src/components/shared/ThumbnailPlaceholder.tsx/~/ThumbnailPlaceholderProps.glyph.html","deprecated":false},{"id":"namespace_thumbnailplaceholderprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ThumbnailPlaceholderProps.className","file":"src/components/shared/ThumbnailPlaceholder.tsx","doc":"","url":"./src/components/shared/ThumbnailPlaceholder.tsx/~/ThumbnailPlaceholderProps.className.html","deprecated":false},{"id":"namespace_thumbnailplaceholder","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"ThumbnailPlaceholder","file":"src/components/shared/ThumbnailPlaceholder.tsx","doc":"Renders the site's colour washed over the theme's surface, with its favicon on top, or its initial when the favicon is missing or fails to load. It fills whatever box it is placed in, from a small thumbnail to a mosaic tile.","url":"./src/components/shared/ThumbnailPlaceholder.tsx/~/ThumbnailPlaceholder.html","deprecated":false},{"id":"namespace_tooltipprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"TooltipProps","file":"src/components/shared/Tooltip.tsx","doc":"Passed to Tooltip by the component that wraps a label in it.","url":"./src/components/shared/Tooltip.tsx/~/TooltipProps.html","deprecated":false},{"id":"namespace_tooltipprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TooltipProps.text","file":"src/components/shared/Tooltip.tsx","doc":"","url":"./src/components/shared/Tooltip.tsx/~/TooltipProps.text.html","deprecated":false},{"id":"namespace_tooltipprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"TooltipProps.children","file":"src/components/shared/Tooltip.tsx","doc":"","url":"./src/components/shared/Tooltip.tsx/~/TooltipProps.children.html","deprecated":false},{"id":"namespace_tooltip","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"Tooltip","file":"src/components/shared/Tooltip.tsx","doc":"Renders children in a <span>, with text above them while the mouse is over them. The tooltip is portaled to <body>, so no container clips it, and it stays where it opened if the page scrolls. It never shows on touch or keyboard focus.","url":"./src/components/shared/Tooltip.tsx/~/Tooltip.html","deprecated":false},{"id":"namespace_communityfeedprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CommunityFeedProps","file":"src/components/social/CommunityFeed.tsx","doc":"Passed to CommunityFeed by whatever shows the feed.","url":"./src/components/social/CommunityFeed.tsx/~/CommunityFeedProps.html","deprecated":false},{"id":"namespace_communityfeedprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommunityFeedProps.feed","file":"src/components/social/CommunityFeed.tsx","doc":"From useCommunityFeed.","url":"./src/components/social/CommunityFeed.tsx/~/CommunityFeedProps.feed.html","deprecated":false},{"id":"namespace_communityfeedprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommunityFeedProps.online","file":"src/components/social/CommunityFeed.tsx","doc":"From useWSPresence: the feed opens on them.","url":"./src/components/social/CommunityFeed.tsx/~/CommunityFeedProps.online.html","deprecated":false},{"id":"namespace_communityfeedprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommunityFeedProps.tabIndex","file":"src/components/social/CommunityFeed.tsx","doc":"Given to every link. -1 takes them out of the tab order, for a second copy of the list such as the one the marquee's loop needs.","url":"./src/components/social/CommunityFeed.tsx/~/CommunityFeedProps.tabIndex.html","deprecated":false},{"id":"namespace_communityfeed","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"CommunityFeed","file":"src/components/social/CommunityFeed.tsx","doc":"Renders the feed as a <ul>: a line for who is online, one for the week's figures, which links to /community, one for its most upvoted dump, then one per event, newest first, ending on how long ago it was. A line with nothing to say is left out. The times are computed at render.","url":"./src/components/social/CommunityFeed.tsx/~/CommunityFeed.html","deprecated":false},{"id":"namespace_followuserbuttonprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"FollowUserButtonProps","file":"src/components/social/FollowButton.tsx","doc":"Passed to FollowUserButton by the UserPublicProfile page.","url":"./src/components/social/FollowButton.tsx/~/FollowUserButtonProps.html","deprecated":false},{"id":"namespace_followuserbuttonprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FollowUserButtonProps.targetUserId","file":"src/components/social/FollowButton.tsx","doc":"","url":"./src/components/social/FollowButton.tsx/~/FollowUserButtonProps.targetUserId.html","deprecated":false},{"id":"namespace_followuserbuttonprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FollowUserButtonProps.targetUsername","file":"src/components/social/FollowButton.tsx","doc":"Names the user in the button's accessible label.","url":"./src/components/social/FollowButton.tsx/~/FollowUserButtonProps.targetUsername.html","deprecated":false},{"id":"namespace_followplaylistbuttonprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"FollowPlaylistButtonProps","file":"src/components/social/FollowButton.tsx","doc":"Passed to FollowPlaylistButton by PlaylistHeader.","url":"./src/components/social/FollowButton.tsx/~/FollowPlaylistButtonProps.html","deprecated":false},{"id":"namespace_followplaylistbuttonprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FollowPlaylistButtonProps.targetPlaylistId","file":"src/components/social/FollowButton.tsx","doc":"","url":"./src/components/social/FollowButton.tsx/~/FollowPlaylistButtonProps.targetPlaylistId.html","deprecated":false},{"id":"namespace_followplaylistbuttonprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FollowPlaylistButtonProps.isPublic","file":"src/components/social/FollowButton.tsx","doc":"Hides the button, since only a public playlist can be followed.","url":"./src/components/social/FollowButton.tsx/~/FollowPlaylistButtonProps.isPublic.html","deprecated":false},{"id":"namespace_followuserbutton","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"FollowUserButton","file":"src/components/social/FollowButton.tsx","doc":"Renders the button that follows or unfollows a user. It renders nothing for a visitor or on the user's own profile, and is disabled until the follows have loaded.","url":"./src/components/social/FollowButton.tsx/~/FollowUserButton.html","deprecated":false},{"id":"namespace_followplaylistbutton","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"FollowPlaylistButton","file":"src/components/social/FollowButton.tsx","doc":"Renders the button that follows or unfollows a playlist. It renders nothing for a visitor or a private playlist, and is disabled until the follows have loaded. Unlike FollowUserButton, it shows on the user's own playlists too.","url":"./src/components/social/FollowButton.tsx/~/FollowPlaylistButton.html","deprecated":false},{"id":"namespace_likebuttonprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"LikeButtonProps","file":"src/components/social/LikeButton.tsx","doc":"Passed to LikeButton by CommentNode, with the state and the functions of WSContext.","url":"./src/components/social/LikeButton.tsx/~/LikeButtonProps.html","deprecated":false},{"id":"namespace_likebuttonprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"LikeButtonProps.commentId","file":"src/components/social/LikeButton.tsx","doc":"","url":"./src/components/social/LikeButton.tsx/~/LikeButtonProps.commentId.html","deprecated":false},{"id":"namespace_likebuttonprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"LikeButtonProps.count","file":"src/components/social/LikeButton.tsx","doc":"The socket's live count if it has one, else the comment's likeCount.","url":"./src/components/social/LikeButton.tsx/~/LikeButtonProps.count.html","deprecated":false},{"id":"namespace_likebuttonprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"LikeButtonProps.liked","file":"src/components/social/LikeButton.tsx","doc":"","url":"./src/components/social/LikeButton.tsx/~/LikeButtonProps.liked.html","deprecated":false},{"id":"namespace_likebuttonprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"LikeButtonProps.disabled","file":"src/components/social/LikeButton.tsx","doc":"Set for a visitor, whom the tooltip asks to log in.","url":"./src/components/social/LikeButton.tsx/~/LikeButtonProps.disabled.html","deprecated":false},{"id":"namespace_likebuttonprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"LikeButtonProps.onLike","file":"src/components/social/LikeButton.tsx","doc":"Called with count, which WSContext needs until it has a live count.","url":"./src/components/social/LikeButton.tsx/~/LikeButtonProps.onLike.html","deprecated":false},{"id":"namespace_likebuttonprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"LikeButtonProps.onUnlike","file":"src/components/social/LikeButton.tsx","doc":"Called with count, as onLike is.","url":"./src/components/social/LikeButton.tsx/~/LikeButtonProps.onUnlike.html","deprecated":false},{"id":"namespace_likebutton","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"LikeButton","file":"src/components/social/LikeButton.tsx","doc":"Renders a comment's like button and its count. Clicking the count, when it isn't zero, opens the list of likers (GET /api/comments/:id/likers) instead.","url":"./src/components/social/LikeButton.tsx/~/LikeButton.html","deprecated":false},{"id":"namespace_usercardprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UserCardProps","file":"src/components/social/UserCard.tsx","doc":"Passed to UserCard by the profile's follow tab and the community page's new members.","url":"./src/components/social/UserCard.tsx/~/UserCardProps.html","deprecated":false},{"id":"namespace_usercardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserCardProps.user","file":"src/components/social/UserCard.tsx","doc":"","url":"./src/components/social/UserCard.tsx/~/UserCardProps.user.html","deprecated":false},{"id":"namespace_usercardprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserCardProps.note","file":"src/components/social/UserCard.tsx","doc":"A line under the name, such as who invited them.","url":"./src/components/social/UserCard.tsx/~/UserCardProps.note.html","deprecated":false},{"id":"namespace_usercard","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"UserCard","file":"src/components/social/UserCard.tsx","doc":"Renders user as an <li> of a .user-card-list, with the follow button, which FollowUserButton hides on the viewer's own card.","url":"./src/components/social/UserCard.tsx/~/UserCard.html","deprecated":false},{"id":"namespace_userlistpopoverprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UserListPopoverProps","file":"src/components/social/UserListPopover.tsx","doc":"Passed to UserListPopover by the button whose count was clicked. The button owns the open state and unmounts the popover in onClose.","url":"./src/components/social/UserListPopover.tsx/~/UserListPopoverProps.html","deprecated":false},{"id":"namespace_userlistpopoverprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserListPopoverProps.anchorRef","file":"src/components/social/UserListPopover.tsx","doc":"","url":"./src/components/social/UserListPopover.tsx/~/UserListPopoverProps.anchorRef.html","deprecated":false},{"id":"namespace_userlistpopoverprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserListPopoverProps.onClose","file":"src/components/social/UserListPopover.tsx","doc":"Called on an outside click, on Escape, and on a scroll outside it.","url":"./src/components/social/UserListPopover.tsx/~/UserListPopoverProps.onClose.html","deprecated":false},{"id":"namespace_userlistpopoverprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserListPopoverProps.fetchUrl","file":"src/components/social/UserListPopover.tsx","doc":"It answers PaginatedData<PublicUser>, a page at a time, and the popover adds page and limit to its query.","url":"./src/components/social/UserListPopover.tsx/~/UserListPopoverProps.fetchUrl.html","deprecated":false},{"id":"namespace_userlistpopover","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"UserListPopover","file":"src/components/social/UserListPopover.tsx","doc":"Renders the users from fetchUrl in a popover next to anchorRef, with a button that loads the next page. It is fixed and portaled to <body>, so a card's overflow can't clip it. It renders nothing until it has measured the anchor.","url":"./src/components/social/UserListPopover.tsx/~/UserListPopover.html","deprecated":false},{"id":"namespace_votebuttonprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"VoteButtonProps","file":"src/components/social/VoteButton.tsx","doc":"Passed to VoteButton by DumpCard, JournalCard and the Dump page, with the state and the functions of WSContext.","url":"./src/components/social/VoteButton.tsx/~/VoteButtonProps.html","deprecated":false},{"id":"namespace_votebuttonprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VoteButtonProps.dumpId","file":"src/components/social/VoteButton.tsx","doc":"","url":"./src/components/social/VoteButton.tsx/~/VoteButtonProps.dumpId.html","deprecated":false},{"id":"namespace_votebuttonprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VoteButtonProps.count","file":"src/components/social/VoteButton.tsx","doc":"The socket's live count if it has one, else the dump's voteCount.","url":"./src/components/social/VoteButton.tsx/~/VoteButtonProps.count.html","deprecated":false},{"id":"namespace_votebuttonprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VoteButtonProps.voted","file":"src/components/social/VoteButton.tsx","doc":"","url":"./src/components/social/VoteButton.tsx/~/VoteButtonProps.voted.html","deprecated":false},{"id":"namespace_votebuttonprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VoteButtonProps.disabled","file":"src/components/social/VoteButton.tsx","doc":"Set for a visitor, whom the tooltip asks to log in.","url":"./src/components/social/VoteButton.tsx/~/VoteButtonProps.disabled.html","deprecated":false},{"id":"namespace_votebuttonprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VoteButtonProps.onCast","file":"src/components/social/VoteButton.tsx","doc":"Called with count, which WSContext needs until it has a live count.","url":"./src/components/social/VoteButton.tsx/~/VoteButtonProps.onCast.html","deprecated":false},{"id":"namespace_votebuttonprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VoteButtonProps.onRemove","file":"src/components/social/VoteButton.tsx","doc":"Called with count, as onCast is.","url":"./src/components/social/VoteButton.tsx/~/VoteButtonProps.onRemove.html","deprecated":false},{"id":"namespace_votebutton","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"VoteButton","file":"src/components/social/VoteButton.tsx","doc":"Renders a dump's upvote button and its count. Clicking the count, when it isn't zero, opens the list of voters (GET /api/dumps/:id/voters) instead.","url":"./src/components/social/VoteButton.tsx/~/VoteButton.html","deprecated":false},{"id":"namespace_api_url","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"API_URL","file":"src/config/api.ts","doc":"The API's origin, which every fetch of the frontend prefixes to its path. It is empty in production, where the API is the page's own origin.","url":"./src/config/api.ts/~/API_URL.html","deprecated":false},{"id":"namespace_ws_url","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"WS_URL","file":"src/config/api.ts","doc":"The socket's origin, for WSProvider. It is always absolute, since WebSocket takes no relative URL.","url":"./src/config/api.ts/~/WS_URL.html","deprecated":false},{"id":"namespace_community_url","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"COMMUNITY_URL","file":"src/config/api.ts","doc":"The community endpoint, for the community page.","url":"./src/config/api.ts/~/COMMUNITY_URL.html","deprecated":false},{"id":"namespace_community_feed_url","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"COMMUNITY_FEED_URL","file":"src/config/api.ts","doc":"The community feed's endpoint, for CommunityFeedProvider.","url":"./src/config/api.ts/~/COMMUNITY_FEED_URL.html","deprecated":false},{"id":"namespace_search_url","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"SEARCH_URL","file":"src/config/api.ts","doc":"The search endpoint, for the search page.","url":"./src/config/api.ts/~/SEARCH_URL.html","deprecated":false},{"id":"namespace_default_page_size","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"DEFAULT_PAGE_SIZE","file":"src/config/api.ts","doc":"How many items a page of a feed or list asks the API for.","url":"./src/config/api.ts/~/DEFAULT_PAGE_SIZE.html","deprecated":false},{"id":"namespace_notifications_page_size","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"NOTIFICATIONS_PAGE_SIZE","file":"src/config/api.ts","doc":"How many notifications a page of /notifications asks the API for.","url":"./src/config/api.ts/~/NOTIFICATIONS_PAGE_SIZE.html","deprecated":false},{"id":"namespace_default_feed_tab","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"DEFAULT_FEED_TAB","file":"src/config/feedTabs.ts","doc":"The tab the bare / and /<category> show visitors, and users who haven't picked one in their settings.","url":"./src/config/feedTabs.ts/~/DEFAULT_FEED_TAB.html","deprecated":false},{"id":"namespace_image_sizes","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"IMAGE_SIZES","file":"src/config/imageSizes.ts","doc":"The width of each image, by the place it is shown.","url":"./src/config/imageSizes.ts/~/IMAGE_SIZES.html","deprecated":false},{"id":"namespace_image_sizes","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"IMAGE_SIZES.compactThumbnail","file":"src/config/imageSizes.ts","doc":"A compact thumbnail at its widest, in a dump card's preview; the rows that show it smaller take the same copy.","url":"./src/config/imageSizes.ts/~/IMAGE_SIZES.compactThumbnail.html","deprecated":false},{"id":"namespace_image_sizes","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"IMAGE_SIZES.richThumbnail","file":"src/config/imageSizes.ts","doc":"A link's thumbnail beside its text, above it on a narrow screen.","url":"./src/config/imageSizes.ts/~/IMAGE_SIZES.richThumbnail.html","deprecated":false},{"id":"namespace_image_sizes","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"IMAGE_SIZES.journal","file":"src/config/imageSizes.ts","doc":"A journal tile's image, by the tile's shape.","url":"./src/config/imageSizes.ts/~/IMAGE_SIZES.journal.html","deprecated":false},{"id":"namespace_image_sizes","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"IMAGE_SIZES.journal.feature","file":"src/config/imageSizes.ts","doc":"","url":"./src/config/imageSizes.ts/~/IMAGE_SIZES.journal.feature.html","deprecated":false},{"id":"namespace_image_sizes","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"IMAGE_SIZES.journal.wide","file":"src/config/imageSizes.ts","doc":"","url":"./src/config/imageSizes.ts/~/IMAGE_SIZES.journal.wide.html","deprecated":false},{"id":"namespace_image_sizes","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"IMAGE_SIZES.journal.tall","file":"src/config/imageSizes.ts","doc":"","url":"./src/config/imageSizes.ts/~/IMAGE_SIZES.journal.tall.html","deprecated":false},{"id":"namespace_image_sizes","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"IMAGE_SIZES.journal.square","file":"src/config/imageSizes.ts","doc":"","url":"./src/config/imageSizes.ts/~/IMAGE_SIZES.journal.square.html","deprecated":false},{"id":"namespace_image_sizes","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"IMAGE_SIZES.playlistThumb","file":"src/config/imageSizes.ts","doc":"A playlist's cover in a row of a list.","url":"./src/config/imageSizes.ts/~/IMAGE_SIZES.playlistThumb.html","deprecated":false},{"id":"namespace_image_sizes","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"IMAGE_SIZES.playlistTile","file":"src/config/imageSizes.ts","doc":"A playlist's cover as a tile of the grid, two to a row when narrow.","url":"./src/config/imageSizes.ts/~/IMAGE_SIZES.playlistTile.html","deprecated":false},{"id":"namespace_image_sizes","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"IMAGE_SIZES.playlistBanner","file":"src/config/imageSizes.ts","doc":"A playlist's cover as the banner of its page.","url":"./src/config/imageSizes.ts/~/IMAGE_SIZES.playlistBanner.html","deprecated":false},{"id":"namespace_image_sizes","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"IMAGE_SIZES.playerArtwork","file":"src/config/imageSizes.ts","doc":"The artwork in the global player's header.","url":"./src/config/imageSizes.ts/~/IMAGE_SIZES.playerArtwork.html","deprecated":false},{"id":"namespace_default_style","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"DEFAULT_STYLE","file":"src/config/instance.ts","doc":"The instance's style, which applies until a visitor or their account picks one. A missing or unknown value means BASE_STYLE. ThemeProvider reads it.","url":"./src/config/instance.ts/~/DEFAULT_STYLE.html","deprecated":false},{"id":"namespace_email_enabled","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"EMAIL_ENABLED","file":"src/config/instance.ts","doc":"Whether the server sends email. Without it the settings page shows the digest switches disabled, with a note why.","url":"./src/config/instance.ts/~/EMAIL_ENABLED.html","deprecated":false},{"id":"namespace_federation_incoming","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"FEDERATION_INCOMING","file":"src/config/instance.ts","doc":"Whether users of other instances sign in here. Without it the login and register pages offer no other instance.","url":"./src/config/instance.ts/~/FEDERATION_INCOMING.html","deprecated":false},{"id":"namespace_federation_outgoing","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"FEDERATION_OUTGOING","file":"src/config/instance.ts","doc":"Whether this instance's users sign in to other instances. Without it the settings page doesn't list the instances they signed in to, since none remain.","url":"./src/config/instance.ts/~/FEDERATION_OUTGOING.html","deprecated":false},{"id":"namespace_bandcampplayer","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"BandcampPlayer","file":"src/config/playerMode.ts","doc":"A Bandcamp player. \"embed\" is Bandcamp's own iframe, \"native\" is the site's player on the resolved streams.","url":"./src/config/playerMode.ts/~/BandcampPlayer.html","deprecated":false},{"id":"namespace_bandcamp_player","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"BANDCAMP_PLAYER","file":"src/config/playerMode.ts","doc":"This deployment's Bandcamp player, read once when the app loads.","url":"./src/config/playerMode.ts/~/BANDCAMP_PLAYER.html","deprecated":false},{"id":"namespace_authcontextvalue","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"AuthContextValue","file":"src/contexts/auth/AuthContext.ts","doc":"Provided by AuthProvider to useAuth, which builds the session's API on it.","url":"./src/contexts/auth/AuthContext.ts/~/AuthContextValue.html","deprecated":false},{"id":"namespace_authcontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AuthContextValue.authResponse","file":"src/contexts/auth/AuthContext.ts","doc":"","url":"./src/contexts/auth/AuthContext.ts/~/AuthContextValue.authResponse.html","deprecated":false},{"id":"namespace_authcontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AuthContextValue.setAuthResponse","file":"src/contexts/auth/AuthContext.ts","doc":"Replaces the session in memory only. Its callers store the new session themselves, with storeSession, so other tabs follow.","url":"./src/contexts/auth/AuthContext.ts/~/AuthContextValue.setAuthResponse.html","deprecated":false},{"id":"namespace_authcontext","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"AuthContext","file":"src/contexts/auth/AuthContext.ts","doc":"The session's context. Its default, a signed-out session whose setter does nothing, is only seen outside AuthProvider, as in some tests.","url":"./src/contexts/auth/AuthContext.ts/~/AuthContext.html","deprecated":false},{"id":"namespace_authproviderprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"AuthProviderProps","file":"src/contexts/auth/AuthProvider.tsx","doc":"Passed to AuthProvider by App.","url":"./src/contexts/auth/AuthProvider.tsx/~/AuthProviderProps.html","deprecated":false},{"id":"namespace_authproviderprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AuthProviderProps.children","file":"src/contexts/auth/AuthProvider.tsx","doc":"","url":"./src/contexts/auth/AuthProvider.tsx/~/AuthProviderProps.children.html","deprecated":false},{"id":"namespace_authprovider","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"AuthProvider","file":"src/contexts/auth/AuthProvider.tsx","doc":"Provides AuthContext. The session starts as the stored one and follows it when another tab changes it. The server checks it on mount and whenever the tab regains focus: a 401 ends it, and a user or settings changed on the server replace the stored ones. A session from before media tokens gets one.","url":"./src/contexts/auth/AuthProvider.tsx/~/AuthProvider.html","deprecated":false},{"id":"namespace_categoriescontextvalue","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CategoriesContextValue","file":"src/contexts/category/CategoriesContext.ts","doc":"Provided by CategoriesProvider to useCategories, for the category switchers and pickers, the dump and playlist pages and cards, and the category manager.","url":"./src/contexts/category/CategoriesContext.ts/~/CategoriesContextValue.html","deprecated":false},{"id":"namespace_categoriescontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CategoriesContextValue.categories","file":"src/contexts/category/CategoriesContext.ts","doc":"Every category, dump and playlist ones, in the server's order, by kind, position then slug.","url":"./src/contexts/category/CategoriesContext.ts/~/CategoriesContextValue.categories.html","deprecated":false},{"id":"namespace_categoriescontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CategoriesContextValue.isLoaded","file":"src/contexts/category/CategoriesContext.ts","doc":"Whether the first fetch has ended. It is also true after a network error, with no categories.","url":"./src/contexts/category/CategoriesContext.ts/~/CategoriesContextValue.isLoaded.html","deprecated":false},{"id":"namespace_categoriescontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CategoriesContextValue.refresh","file":"src/contexts/category/CategoriesContext.ts","doc":"Refetches the list. The category manager calls it after each change.","url":"./src/contexts/category/CategoriesContext.ts/~/CategoriesContextValue.refresh.html","deprecated":false},{"id":"namespace_categoriescontext","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"CategoriesContext","file":"src/contexts/category/CategoriesContext.ts","doc":"The categories' context. Its default, an empty list never loaded, is only seen outside CategoriesProvider.","url":"./src/contexts/category/CategoriesContext.ts/~/CategoriesContext.html","deprecated":false},{"id":"namespace_categoriesproviderprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CategoriesProviderProps","file":"src/contexts/category/CategoriesProvider.tsx","doc":"Passed to CategoriesProvider by App.","url":"./src/contexts/category/CategoriesProvider.tsx/~/CategoriesProviderProps.html","deprecated":false},{"id":"namespace_categoriesproviderprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CategoriesProviderProps.children","file":"src/contexts/category/CategoriesProvider.tsx","doc":"","url":"./src/contexts/category/CategoriesProvider.tsx/~/CategoriesProviderProps.children.html","deprecated":false},{"id":"namespace_categoriesprovider","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"CategoriesProvider","file":"src/contexts/category/CategoriesProvider.tsx","doc":"Provides CategoriesContext, fetching the categories on mount. Until a fetch succeeds, isLoaded stays false, so that no page takes an empty list for the truth and answers a category's URL with a 404; a failed first fetch is tried again 10 s later. A failed refresh keeps the previous list.","url":"./src/contexts/category/CategoriesProvider.tsx/~/CategoriesProvider.html","deprecated":false},{"id":"namespace_chatcontextvalue","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ChatContextValue","file":"src/contexts/chat/ChatContext.ts","doc":"Provided by ChatProvider through ChatContext. The modal closes itself, so opening is all its callers need.","url":"./src/contexts/chat/ChatContext.ts/~/ChatContextValue.html","deprecated":false},{"id":"namespace_chatcontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatContextValue.openChat","file":"src/contexts/chat/ChatContext.ts","doc":"Does nothing for a visitor.","url":"./src/contexts/chat/ChatContext.ts/~/ChatContextValue.openChat.html","deprecated":false},{"id":"namespace_chatcontext","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"ChatContext","file":"src/contexts/chat/ChatContext.ts","doc":"Opens the chat modal. Outside ChatProvider it does nothing.","url":"./src/contexts/chat/ChatContext.ts/~/ChatContext.html","deprecated":false},{"id":"namespace_chatproviderprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ChatProviderProps","file":"src/contexts/chat/ChatProvider.tsx","doc":"Passed to ChatProvider by App.","url":"./src/contexts/chat/ChatProvider.tsx/~/ChatProviderProps.html","deprecated":false},{"id":"namespace_chatproviderprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatProviderProps.children","file":"src/contexts/chat/ChatProvider.tsx","doc":"","url":"./src/contexts/chat/ChatProvider.tsx/~/ChatProviderProps.children.html","deprecated":false},{"id":"namespace_chatprovider","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"ChatProvider","file":"src/contexts/chat/ChatProvider.tsx","doc":"Provides ChatContext and renders the one chat modal while it is open. openChat opens it, and so does a ?chat= query parameter on any page: ?chat=open, or ?chat=<message id> to open on that message, which is where a chat mention notification links. It stays closed for visitors.","url":"./src/contexts/chat/ChatProvider.tsx/~/ChatProvider.html","deprecated":false},{"id":"namespace_playeritembase","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PlayerItemBase","file":"src/contexts/player/PlayerContext.ts","doc":"The fields of every PlayerItem, which GlobalPlayer's header shows.","url":"./src/contexts/player/PlayerContext.ts/~/PlayerItemBase.html","deprecated":false},{"id":"namespace_playeritembase","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlayerItemBase.title","file":"src/contexts/player/PlayerContext.ts","doc":"","url":"./src/contexts/player/PlayerContext.ts/~/PlayerItemBase.title.html","deprecated":false},{"id":"namespace_playeritembase","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlayerItemBase.dumpHref","file":"src/contexts/player/PlayerContext.ts","doc":"The dump page the header's title links to.","url":"./src/contexts/player/PlayerContext.ts/~/PlayerItemBase.dumpHref.html","deprecated":false},{"id":"namespace_playeritembase","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlayerItemBase.artworkUrl","file":"src/contexts/player/PlayerContext.ts","doc":"A raw URL, which Thumbnail proxies when it must.","url":"./src/contexts/player/PlayerContext.ts/~/PlayerItemBase.artworkUrl.html","deprecated":false},{"id":"namespace_playeritembase","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlayerItemBase.subtitle","file":"src/contexts/player/PlayerContext.ts","doc":"Shown under the title. It holds the artist, the site's name or the file's name.","url":"./src/contexts/player/PlayerContext.ts/~/PlayerItemBase.subtitle.html","deprecated":false},{"id":"namespace_playeritem","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"PlayerItem","file":"src/contexts/player/PlayerContext.ts","doc":"Built by the cards and previews that start playback, and held in PlayerProvider's queue, which localStorage keeps across reloads. An embed plays in the provider's iframe; a file (an upload) and a stream play in MediaPlayer.","url":"./src/contexts/player/PlayerContext.ts/~/PlayerItem.html","deprecated":false},{"id":"namespace_playeritemkey","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"playerItemKey","file":"src/contexts/player/PlayerContext.ts","doc":"Returns a key that identifies item whatever its stream URL, so that a re-resolved track is still the same track. GlobalPlayer keys its tracklist on it and tells a new item by it; PlayerProvider tells repeated failures of one track by it.","url":"./src/contexts/player/PlayerContext.ts/~/playerItemKey.html","deprecated":false},{"id":"namespace_playercontextvalue","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PlayerContextValue","file":"src/contexts/player/PlayerContext.ts","doc":"Provided by PlayerProvider through PlayerContext. Cards and previews read what plays and call the controls; GlobalPlayer and MediaPlayer use the internal fields to report the media's state back.","url":"./src/contexts/player/PlayerContext.ts/~/PlayerContextValue.html","deprecated":false},{"id":"namespace_playercontextvalue","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"PlayerContextValue.play","file":"src/contexts/player/PlayerContext.ts","doc":"Plays item alone, replacing the queue.","url":"./src/contexts/player/PlayerContext.ts/~/PlayerContextValue.play.html","deprecated":false},{"id":"namespace_playercontextvalue","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"PlayerContextValue.playQueue","file":"src/contexts/player/PlayerContext.ts","doc":"Replaces the queue with items and plays it from startIndex.","url":"./src/contexts/player/PlayerContext.ts/~/PlayerContextValue.playQueue.html","deprecated":false},{"id":"namespace_playercontextvalue","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"PlayerContextValue.playAt","file":"src/contexts/player/PlayerContext.ts","doc":"Plays the queue's item at index, or restarts it when it is current.","url":"./src/contexts/player/PlayerContext.ts/~/PlayerContextValue.playAt.html","deprecated":false},{"id":"namespace_playercontextvalue","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"PlayerContextValue.next","file":"src/contexts/player/PlayerContext.ts","doc":"","url":"./src/contexts/player/PlayerContext.ts/~/PlayerContextValue.next.html","deprecated":false},{"id":"namespace_playercontextvalue","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"PlayerContextValue.previous","file":"src/contexts/player/PlayerContext.ts","doc":"Restarts the item after its first 3 seconds, else plays the previous one.","url":"./src/contexts/player/PlayerContext.ts/~/PlayerContextValue.previous.html","deprecated":false},{"id":"namespace_playercontextvalue","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"PlayerContextValue.stop","file":"src/contexts/player/PlayerContext.ts","doc":"Empties the queue, which closes the player.","url":"./src/contexts/player/PlayerContext.ts/~/PlayerContextValue.stop.html","deprecated":false},{"id":"namespace_playercontextvalue","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"PlayerContextValue.seekTo","file":"src/contexts/player/PlayerContext.ts","doc":"Seeks a file or stream to time seconds. An embed doesn't move.","url":"./src/contexts/player/PlayerContext.ts/~/PlayerContextValue.seekTo.html","deprecated":false},{"id":"namespace_playercontextvalue","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"PlayerContextValue.togglePlay","file":"src/contexts/player/PlayerContext.ts","doc":"Pauses or resumes a file or stream. An embed has its own controls.","url":"./src/contexts/player/PlayerContext.ts/~/PlayerContextValue.togglePlay.html","deprecated":false},{"id":"namespace_playercontextvalue","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"PlayerContextValue.onPlayStateChange","file":"src/contexts/player/PlayerContext.ts","doc":"Called by MediaPlayer when its media starts or stops.","url":"./src/contexts/player/PlayerContext.ts/~/PlayerContextValue.onPlayStateChange.html","deprecated":false},{"id":"namespace_playercontextvalue","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"PlayerContextValue.onTimeUpdate","file":"src/contexts/player/PlayerContext.ts","doc":"Called by MediaPlayer as its media plays.","url":"./src/contexts/player/PlayerContext.ts/~/PlayerContextValue.onTimeUpdate.html","deprecated":false},{"id":"namespace_playercontextvalue","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"PlayerContextValue.onEnded","file":"src/contexts/player/PlayerContext.ts","doc":"Called by MediaPlayer at its media's end, to play the next item.","url":"./src/contexts/player/PlayerContext.ts/~/PlayerContextValue.onEnded.html","deprecated":false},{"id":"namespace_playercontextvalue","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"PlayerContextValue.onError","file":"src/contexts/player/PlayerContext.ts","doc":"Called by MediaPlayer when its media fails, to re-resolve a stream.","url":"./src/contexts/player/PlayerContext.ts/~/PlayerContextValue.onError.html","deprecated":false},{"id":"namespace_playercontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlayerContextValue.current","file":"src/contexts/player/PlayerContext.ts","doc":"Always queue[queueIndex], or null when nothing plays.","url":"./src/contexts/player/PlayerContext.ts/~/PlayerContextValue.current.html","deprecated":false},{"id":"namespace_playercontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlayerContextValue.playing","file":"src/contexts/player/PlayerContext.ts","doc":"","url":"./src/contexts/player/PlayerContext.ts/~/PlayerContextValue.playing.html","deprecated":false},{"id":"namespace_playercontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlayerContextValue.queue","file":"src/contexts/player/PlayerContext.ts","doc":"The queue. Every playback is a queue of at least one item, so single tracks and albums share one code path.","url":"./src/contexts/player/PlayerContext.ts/~/PlayerContextValue.queue.html","deprecated":false},{"id":"namespace_playercontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlayerContextValue.queueIndex","file":"src/contexts/player/PlayerContext.ts","doc":"","url":"./src/contexts/player/PlayerContext.ts/~/PlayerContextValue.queueIndex.html","deprecated":false},{"id":"namespace_playercontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlayerContextValue.hasNext","file":"src/contexts/player/PlayerContext.ts","doc":"","url":"./src/contexts/player/PlayerContext.ts/~/PlayerContextValue.hasNext.html","deprecated":false},{"id":"namespace_playercontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlayerContextValue.hasPrevious","file":"src/contexts/player/PlayerContext.ts","doc":"","url":"./src/contexts/player/PlayerContext.ts/~/PlayerContextValue.hasPrevious.html","deprecated":false},{"id":"namespace_playercontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlayerContextValue.resolving","file":"src/contexts/player/PlayerContext.ts","doc":"True while a stream's URLs are re-resolved, which GlobalPlayer shows.","url":"./src/contexts/player/PlayerContext.ts/~/PlayerContextValue.resolving.html","deprecated":false},{"id":"namespace_playercontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlayerContextValue.startTime","file":"src/contexts/player/PlayerContext.ts","doc":"Where MediaPlayer starts the current item, in seconds: not 0 only for an item restored from a previous session, or resumed after a re-resolve.","url":"./src/contexts/player/PlayerContext.ts/~/PlayerContextValue.startTime.html","deprecated":false},{"id":"namespace_playercontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlayerContextValue.autoplay","file":"src/contexts/player/PlayerContext.ts","doc":"Whether the current item starts on mount. A restored session appears paused, since no user gesture is behind it; a fresh play() autoplays.","url":"./src/contexts/player/PlayerContext.ts/~/PlayerContextValue.autoplay.html","deprecated":false},{"id":"namespace_playercontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlayerContextValue.seekRef","file":"src/contexts/player/PlayerContext.ts","doc":"Where the mounted MediaPlayer registers its seek handle, for seekTo.","url":"./src/contexts/player/PlayerContext.ts/~/PlayerContextValue.seekRef.html","deprecated":false},{"id":"namespace_playercontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlayerContextValue.seekRef.current","file":"src/contexts/player/PlayerContext.ts","doc":"","url":"./src/contexts/player/PlayerContext.ts/~/PlayerContextValue.seekRef.current.html","deprecated":false},{"id":"namespace_playercontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlayerContextValue.toggleRef","file":"src/contexts/player/PlayerContext.ts","doc":"Where the mounted MediaPlayer registers its play/pause handle.","url":"./src/contexts/player/PlayerContext.ts/~/PlayerContextValue.toggleRef.html","deprecated":false},{"id":"namespace_playercontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlayerContextValue.toggleRef.current","file":"src/contexts/player/PlayerContext.ts","doc":"","url":"./src/contexts/player/PlayerContext.ts/~/PlayerContextValue.toggleRef.current.html","deprecated":false},{"id":"namespace_defaultplayervalue","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"defaultPlayerValue","file":"src/contexts/player/PlayerContext.ts","doc":"Given by PlayerContext outside PlayerProvider: nothing plays and no control does anything. The tests' render helper starts from it.","url":"./src/contexts/player/PlayerContext.ts/~/defaultPlayerValue.html","deprecated":false},{"id":"namespace_playercontext","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"PlayerContext","file":"src/contexts/player/PlayerContext.ts","doc":"The player's state and controls, from PlayerProvider.","url":"./src/contexts/player/PlayerContext.ts/~/PlayerContext.html","deprecated":false},{"id":"namespace_playertimevalue","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PlayerTimeValue","file":"src/contexts/player/PlayerContext.ts","doc":"Provided by PlayerProvider through PlayerTimeContext, apart from the rest because it changes several times a second while something plays. Only what draws a position, like the dump page's audio preview, reads it, so the cards that read PlayerContext don't re-render with it.","url":"./src/contexts/player/PlayerContext.ts/~/PlayerTimeValue.html","deprecated":false},{"id":"namespace_playertimevalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlayerTimeValue.currentTime","file":"src/contexts/player/PlayerContext.ts","doc":"In seconds.","url":"./src/contexts/player/PlayerContext.ts/~/PlayerTimeValue.currentTime.html","deprecated":false},{"id":"namespace_playertimevalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlayerTimeValue.duration","file":"src/contexts/player/PlayerContext.ts","doc":"In seconds, 0 until the media's metadata loads.","url":"./src/contexts/player/PlayerContext.ts/~/PlayerTimeValue.duration.html","deprecated":false},{"id":"namespace_defaultplayertimevalue","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"defaultPlayerTimeValue","file":"src/contexts/player/PlayerContext.ts","doc":"Given by PlayerTimeContext outside PlayerProvider.","url":"./src/contexts/player/PlayerContext.ts/~/defaultPlayerTimeValue.html","deprecated":false},{"id":"namespace_playertimecontext","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"PlayerTimeContext","file":"src/contexts/player/PlayerContext.ts","doc":"The playhead of the current file or stream, from PlayerProvider.","url":"./src/contexts/player/PlayerContext.ts/~/PlayerTimeContext.html","deprecated":false},{"id":"namespace_playerproviderprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PlayerProviderProps","file":"src/contexts/player/PlayerProvider.tsx","doc":"Passed to PlayerProvider by App, around the whole app.","url":"./src/contexts/player/PlayerProvider.tsx/~/PlayerProviderProps.html","deprecated":false},{"id":"namespace_playerproviderprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlayerProviderProps.children","file":"src/contexts/player/PlayerProvider.tsx","doc":"","url":"./src/contexts/player/PlayerProvider.tsx/~/PlayerProviderProps.children.html","deprecated":false},{"id":"namespace_playerprovider","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"PlayerProvider","file":"src/contexts/player/PlayerProvider.tsx","doc":"Provides PlayerContext and PlayerTimeContext. The queue and the position are saved as they change and restored on load, paused; signing out, or in as someone else, closes the player. A stream whose signed URL expires is re-resolved and resumed where it was, and falls back to its embed if that fails.","url":"./src/contexts/player/PlayerProvider.tsx/~/PlayerProvider.html","deprecated":false},{"id":"namespace_communityfeedcontextvalue","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CommunityFeedContextValue","file":"src/contexts/social/CommunityFeedContext.ts","doc":"Provided by CommunityFeedProvider through CommunityFeedContext.","url":"./src/contexts/social/CommunityFeedContext.ts/~/CommunityFeedContextValue.html","deprecated":false},{"id":"namespace_communityfeedcontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommunityFeedContextValue.feed","file":"src/contexts/social/CommunityFeedContext.ts","doc":"Null until it is fetched, which waits for a first watch, and always for a visitor: the feed is for signed-in users.","url":"./src/contexts/social/CommunityFeedContext.ts/~/CommunityFeedContextValue.feed.html","deprecated":false},{"id":"namespace_communityfeedcontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommunityFeedContextValue.watch","file":"src/contexts/social/CommunityFeedContext.ts","doc":"Says a component is showing the feed, until the returned call. The feed is fetched, and kept up to date, only while one is: most styles show it nowhere. useCommunityFeed calls it.","url":"./src/contexts/social/CommunityFeedContext.ts/~/CommunityFeedContextValue.watch.html","deprecated":false},{"id":"namespace_defaultcommunityfeedvalue","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"defaultCommunityFeedValue","file":"src/contexts/social/CommunityFeedContext.ts","doc":"Given to a consumer outside CommunityFeedProvider: no feed.","url":"./src/contexts/social/CommunityFeedContext.ts/~/defaultCommunityFeedValue.html","deprecated":false},{"id":"namespace_communityfeedcontext","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"CommunityFeedContext","file":"src/contexts/social/CommunityFeedContext.ts","doc":"Provided by CommunityFeedProvider, and read with useCommunityFeed.","url":"./src/contexts/social/CommunityFeedContext.ts/~/CommunityFeedContext.html","deprecated":false},{"id":"namespace_communityfeedproviderprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CommunityFeedProviderProps","file":"src/contexts/social/CommunityFeedProvider.tsx","doc":"Passed to CommunityFeedProvider by App.","url":"./src/contexts/social/CommunityFeedProvider.tsx/~/CommunityFeedProviderProps.html","deprecated":false},{"id":"namespace_communityfeedproviderprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommunityFeedProviderProps.children","file":"src/contexts/social/CommunityFeedProvider.tsx","doc":"","url":"./src/contexts/social/CommunityFeedProvider.tsx/~/CommunityFeedProviderProps.children.html","deprecated":false},{"id":"namespace_communityfeedprovider","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"CommunityFeedProvider","file":"src/contexts/social/CommunityFeedProvider.tsx","doc":"Provides CommunityFeedContext. It fetches the feed once a component watches it, for the signed-in user alone. The socket's messages don't carry a feed's lines, an upvote's naming neither its dump nor its voter, so each one that may change the feed has it fetched again, and the server's query stays the one place that decides what the feed holds. A change that comes while nothing watches is caught up with on the next watch.","url":"./src/contexts/social/CommunityFeedProvider.tsx/~/CommunityFeedProvider.html","deprecated":false},{"id":"namespace_followcontextvalue","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"FollowContextValue","file":"src/contexts/social/FollowContext.ts","doc":"Provided by FollowProvider through FollowContext. The four functions change the sets at once and undo the change when the request fails. They resolve to whether it worked, and never reject.","url":"./src/contexts/social/FollowContext.ts/~/FollowContextValue.html","deprecated":false},{"id":"namespace_followcontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FollowContextValue.followedUserIds","file":"src/contexts/social/FollowContext.ts","doc":"","url":"./src/contexts/social/FollowContext.ts/~/FollowContextValue.followedUserIds.html","deprecated":false},{"id":"namespace_followcontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FollowContextValue.followedPlaylistIds","file":"src/contexts/social/FollowContext.ts","doc":"","url":"./src/contexts/social/FollowContext.ts/~/FollowContextValue.followedPlaylistIds.html","deprecated":false},{"id":"namespace_followcontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FollowContextValue.followUser","file":"src/contexts/social/FollowContext.ts","doc":"","url":"./src/contexts/social/FollowContext.ts/~/FollowContextValue.followUser.html","deprecated":false},{"id":"namespace_followcontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FollowContextValue.unfollowUser","file":"src/contexts/social/FollowContext.ts","doc":"","url":"./src/contexts/social/FollowContext.ts/~/FollowContextValue.unfollowUser.html","deprecated":false},{"id":"namespace_followcontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FollowContextValue.followPlaylist","file":"src/contexts/social/FollowContext.ts","doc":"","url":"./src/contexts/social/FollowContext.ts/~/FollowContextValue.followPlaylist.html","deprecated":false},{"id":"namespace_followcontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FollowContextValue.unfollowPlaylist","file":"src/contexts/social/FollowContext.ts","doc":"","url":"./src/contexts/social/FollowContext.ts/~/FollowContextValue.unfollowPlaylist.html","deprecated":false},{"id":"namespace_followcontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FollowContextValue.isLoaded","file":"src/contexts/social/FollowContext.ts","doc":"False until the follows are fetched, and always for a visitor. The sets are empty until then, so a button would show \"Follow\" for a followed user. A failed fetch keeps it false, and is tried again 10 s later.","url":"./src/contexts/social/FollowContext.ts/~/FollowContextValue.isLoaded.html","deprecated":false},{"id":"namespace_defaultfollowvalue","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"defaultFollowValue","file":"src/contexts/social/FollowContext.ts","doc":"Given to a consumer outside FollowProvider, for which nothing is followed.","url":"./src/contexts/social/FollowContext.ts/~/defaultFollowValue.html","deprecated":false},{"id":"namespace_followcontext","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"FollowContext","file":"src/contexts/social/FollowContext.ts","doc":"Tells the Follow buttons what the signed-in user follows. Read it with useFollows.","url":"./src/contexts/social/FollowContext.ts/~/FollowContext.html","deprecated":false},{"id":"namespace_followproviderprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"FollowProviderProps","file":"src/contexts/social/FollowProvider.tsx","doc":"Passed to FollowProvider by App.","url":"./src/contexts/social/FollowProvider.tsx/~/FollowProviderProps.html","deprecated":false},{"id":"namespace_followproviderprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FollowProviderProps.children","file":"src/contexts/social/FollowProvider.tsx","doc":"","url":"./src/contexts/social/FollowProvider.tsx/~/FollowProviderProps.children.html","deprecated":false},{"id":"namespace_followprovider","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"FollowProvider","file":"src/contexts/social/FollowProvider.tsx","doc":"Provides FollowContext. It fetches the follows whenever the token changes, again when follows_changed says another tab changed them, and after the socket reconnects. It empties them on sign-out.","url":"./src/contexts/social/FollowProvider.tsx/~/FollowProvider.html","deprecated":false},{"id":"namespace_themecontextvalue","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ThemeContextValue","file":"src/contexts/theme/ThemeContext.ts","doc":"Provided by ThemeProvider to useTheme. A setter applies the choice and stores it in this browser, and in the account's settings when signed in.","url":"./src/contexts/theme/ThemeContext.ts/~/ThemeContextValue.html","deprecated":false},{"id":"namespace_themecontextvalue","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"ThemeContextValue.setStyle","file":"src/contexts/theme/ThemeContext.ts","doc":"","url":"./src/contexts/theme/ThemeContext.ts/~/ThemeContextValue.setStyle.html","deprecated":false},{"id":"namespace_themecontextvalue","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"ThemeContextValue.setColorScheme","file":"src/contexts/theme/ThemeContext.ts","doc":"","url":"./src/contexts/theme/ThemeContext.ts/~/ThemeContextValue.setColorScheme.html","deprecated":false},{"id":"namespace_themecontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ThemeContextValue.style","file":"src/contexts/theme/ThemeContext.ts","doc":"","url":"./src/contexts/theme/ThemeContext.ts/~/ThemeContextValue.style.html","deprecated":false},{"id":"namespace_themecontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ThemeContextValue.colorScheme","file":"src/contexts/theme/ThemeContext.ts","doc":"","url":"./src/contexts/theme/ThemeContext.ts/~/ThemeContextValue.colorScheme.html","deprecated":false},{"id":"namespace_themecontext","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"ThemeContext","file":"src/contexts/theme/ThemeContext.ts","doc":"The theme's context. Its default is only seen outside ThemeProvider.","url":"./src/contexts/theme/ThemeContext.ts/~/ThemeContext.html","deprecated":false},{"id":"namespace_themeproviderprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ThemeProviderProps","file":"src/contexts/theme/ThemeProvider.tsx","doc":"Passed to ThemeProvider by App.","url":"./src/contexts/theme/ThemeProvider.tsx/~/ThemeProviderProps.html","deprecated":false},{"id":"namespace_themeproviderprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ThemeProviderProps.children","file":"src/contexts/theme/ThemeProvider.tsx","doc":"","url":"./src/contexts/theme/ThemeProvider.tsx/~/ThemeProviderProps.children.html","deprecated":false},{"id":"namespace_themeprovider","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"ThemeProvider","file":"src/contexts/theme/ThemeProvider.tsx","doc":"Provides ThemeContext. Each half of the theme goes through useThemeChoice, which sets it on the root element as data-style or data-color-scheme and mirrors it to localStorage, where an inline script in index.html applies it before the first paint, so the page doesn't flash another theme. The two must agree. When an account has no choice yet and this browser has one, it is saved to the account, once per session.","url":"./src/contexts/theme/ThemeProvider.tsx/~/ThemeProvider.html","deprecated":false},{"id":"namespace_avataroverride","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"AvatarOverride","file":"src/contexts/ws/AvatarOverrideContext.ts","doc":"Set by WSProvider for a user whose profile changed, and read by Avatar, where it wins over the possibly stale props the page fetched.","url":"./src/contexts/ws/AvatarOverrideContext.ts/~/AvatarOverride.html","deprecated":false},{"id":"namespace_avataroverride","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AvatarOverride.hasAvatar","file":"src/contexts/ws/AvatarOverrideContext.ts","doc":"","url":"./src/contexts/ws/AvatarOverrideContext.ts/~/AvatarOverride.hasAvatar.html","deprecated":false},{"id":"namespace_avataroverride","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AvatarOverride.version","file":"src/contexts/ws/AvatarOverrideContext.ts","doc":"The user's updatedAt in ms, or the arrival time without one. It busts the cached image.","url":"./src/contexts/ws/AvatarOverrideContext.ts/~/AvatarOverride.version.html","deprecated":false},{"id":"namespace_avataroverridecontext","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"AvatarOverrideContext","file":"src/contexts/ws/AvatarOverrideContext.ts","doc":"Shows changed avatars without a reload, as an AvatarOverride by user id. It is apart from WSContext, so the many avatars of a page don't re-render on every vote or comment.","url":"./src/contexts/ws/AvatarOverrideContext.ts/~/AvatarOverrideContext.html","deprecated":false},{"id":"namespace_voteevent","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"VoteEvent","file":"src/contexts/ws/WSContext.ts","doc":"Keeps a user's upvoted list live, on their profile's overview and tab. WSProvider emits it as a vote event on each votes_update, and useUpvotedList adds or drops the dump.","url":"./src/contexts/ws/WSContext.ts/~/VoteEvent.html","deprecated":false},{"id":"namespace_voteevent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VoteEvent.dumpId","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/VoteEvent.dumpId.html","deprecated":false},{"id":"namespace_voteevent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VoteEvent.voterId","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/VoteEvent.voterId.html","deprecated":false},{"id":"namespace_voteevent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VoteEvent.action","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/VoteEvent.action.html","deprecated":false},{"id":"namespace_playlistevent","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PlaylistEvent","file":"src/contexts/ws/WSContext.ts","doc":"Keeps the playlists on screen up to date, in lists, on a playlist's page and on a dump's page. WSProvider emits it as a playlist event on each playlist_* message; lists apply it through usePlaylistListSync, a playlist's page through usePlaylist. Which fields are set depends on type.","url":"./src/contexts/ws/WSContext.ts/~/PlaylistEvent.html","deprecated":false},{"id":"namespace_playlistevent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistEvent.type","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/PlaylistEvent.type.html","deprecated":false},{"id":"namespace_playlistevent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistEvent.playlistId","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/PlaylistEvent.playlistId.html","deprecated":false},{"id":"namespace_playlistevent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistEvent.playlist","file":"src/contexts/ws/WSContext.ts","doc":"Set when created or updated.","url":"./src/contexts/ws/WSContext.ts/~/PlaylistEvent.playlist.html","deprecated":false},{"id":"namespace_playlistevent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistEvent.userId","file":"src/contexts/ws/WSContext.ts","doc":"The owner's id, set when deleted.","url":"./src/contexts/ws/WSContext.ts/~/PlaylistEvent.userId.html","deprecated":false},{"id":"namespace_playlistevent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistEvent.dumpIds","file":"src/contexts/ws/WSContext.ts","doc":"Set when the dumps changed. It lists only the dumps this user may see, in order.","url":"./src/contexts/ws/WSContext.ts/~/PlaylistEvent.dumpIds.html","deprecated":false},{"id":"namespace_playlistevent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistEvent.lastDumpAt","file":"src/contexts/ws/WSContext.ts","doc":"With dumpIds, when the latest of them was added; undefined when there is none.","url":"./src/contexts/ws/WSContext.ts/~/PlaylistEvent.lastDumpAt.html","deprecated":false},{"id":"namespace_commentevent","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"CommentEvent","file":"src/contexts/ws/WSContext.ts","doc":"Keeps comment threads and comment counts live. WSProvider emits it as a comment event on each comment_* message; the Dump page applies it to its thread, and useDumpListSync to the counts on dump cards.","url":"./src/contexts/ws/WSContext.ts/~/CommentEvent.html","deprecated":false},{"id":"namespace_commentevent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentEvent.type","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/CommentEvent.type.html","deprecated":false},{"id":"namespace_commentevent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentEvent.dumpId","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/CommentEvent.dumpId.html","deprecated":false},{"id":"namespace_commentevent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentEvent.comment","file":"src/contexts/ws/WSContext.ts","doc":"Set when created or updated.","url":"./src/contexts/ws/WSContext.ts/~/CommentEvent.comment.html","deprecated":false},{"id":"namespace_commentevent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"CommentEvent.commentId","file":"src/contexts/ws/WSContext.ts","doc":"Set when deleted.","url":"./src/contexts/ws/WSContext.ts/~/CommentEvent.commentId.html","deprecated":false},{"id":"namespace_dumpevent","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"DumpEvent","file":"src/contexts/ws/WSContext.ts","doc":"Keeps every dump on screen up to date. WSProvider emits it as a dump event on each dump_created and dump_updated; useDumpListSync applies it to lists, and the Dump page to its dump. A dump that turns public comes created to those who couldn't see it.","url":"./src/contexts/ws/WSContext.ts/~/DumpEvent.html","deprecated":false},{"id":"namespace_dumpevent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpEvent.type","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/DumpEvent.type.html","deprecated":false},{"id":"namespace_dumpevent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpEvent.dump","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/DumpEvent.dump.html","deprecated":false},{"id":"namespace_relatedevent","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"RelatedEvent","file":"src/contexts/ws/WSContext.ts","doc":"Keeps the related dumps on a dump's page live. WSProvider emits it as a related event on each dump_related_changed, and the Dump page fetches its related dumps again when dumpIds names its dump.","url":"./src/contexts/ws/WSContext.ts/~/RelatedEvent.html","deprecated":false},{"id":"namespace_relatedevent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RelatedEvent.dumpIds","file":"src/contexts/ws/WSContext.ts","doc":"The dumps this user may see whose related dumps changed.","url":"./src/contexts/ws/WSContext.ts/~/RelatedEvent.dumpIds.html","deprecated":false},{"id":"namespace_userevent","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UserEvent","file":"src/contexts/ws/WSContext.ts","doc":"Keeps a user's profile, and their name on what they posted, up to date. WSProvider emits it as a user event on each user_updated, which the server sends on any change to a profile; useProfile applies it to the profile page, and the list sync hooks to the names on cards.","url":"./src/contexts/ws/WSContext.ts/~/UserEvent.html","deprecated":false},{"id":"namespace_userevent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UserEvent.user","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/UserEvent.user.html","deprecated":false},{"id":"namespace_wsevents","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"WSEvents","file":"src/contexts/ws/WSContext.ts","doc":"The events WSProvider passes on, by kind, to the components that subscribe with useWSEvent. Unlike the state of WSContext, every event reaches every subscriber, however many arrive before the next render. categories says the categories changed, and carries nothing.","url":"./src/contexts/ws/WSContext.ts/~/WSEvents.html","deprecated":false},{"id":"namespace_wsevents","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSEvents.vote","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/WSEvents.vote.html","deprecated":false},{"id":"namespace_wsevents","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSEvents.dump","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/WSEvents.dump.html","deprecated":false},{"id":"namespace_wsevents","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSEvents.related","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/WSEvents.related.html","deprecated":false},{"id":"namespace_wsevents","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSEvents.playlist","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/WSEvents.playlist.html","deprecated":false},{"id":"namespace_wsevents","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSEvents.comment","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/WSEvents.comment.html","deprecated":false},{"id":"namespace_wsevents","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSEvents.user","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/WSEvents.user.html","deprecated":false},{"id":"namespace_wsevents","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSEvents.notification","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/WSEvents.notification.html","deprecated":false},{"id":"namespace_wsevents","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSEvents.categories","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/WSEvents.categories.html","deprecated":false},{"id":"namespace_wseventbus","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"WSEventBus","file":"src/contexts/ws/WSContext.ts","doc":"Delivers WSEvents to their subscribers. WSProvider creates one with createWSEventBus and emits on it as messages arrive; components subscribe through WSEventsContext, and tests emit on their own.","url":"./src/contexts/ws/WSContext.ts/~/WSEventBus.html","deprecated":false},{"id":"namespace_wseventbus","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSEventBus.subscribe","file":"src/contexts/ws/WSContext.ts","doc":"Calls handler with each event of kind, until the returned call.","url":"./src/contexts/ws/WSContext.ts/~/WSEventBus.subscribe.html","deprecated":false},{"id":"namespace_wseventbus","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSEventBus.emit","file":"src/contexts/ws/WSContext.ts","doc":"Calls the handlers of kind now, in the order they subscribed.","url":"./src/contexts/ws/WSContext.ts/~/WSEventBus.emit.html","deprecated":false},{"id":"namespace_createwseventbus","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"createWSEventBus","file":"src/contexts/ws/WSContext.ts","doc":"Returns a bus with no subscribers.","url":"./src/contexts/ws/WSContext.ts/~/createWSEventBus.html","deprecated":false},{"id":"namespace_chatreplytarget","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ChatReplyTarget","file":"src/contexts/ws/WSContext.ts","doc":"Quotes the message a chat message replies to. ChatModal shows it in the reply bar once the user picks it, and it stays on the pending message so the quote shows before the server's echo. Only id goes to the server.","url":"./src/contexts/ws/WSContext.ts/~/ChatReplyTarget.html","deprecated":false},{"id":"namespace_chatreplytarget","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatReplyTarget.id","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/ChatReplyTarget.id.html","deprecated":false},{"id":"namespace_chatreplytarget","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatReplyTarget.author","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/ChatReplyTarget.author.html","deprecated":false},{"id":"namespace_chatreplytarget","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatReplyTarget.body","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/ChatReplyTarget.body.html","deprecated":false},{"id":"namespace_pendingchatmessage","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PendingChatMessage","file":"src/contexts/ws/WSContext.ts","doc":"Shows a chat message the moment the user sends it, and lets them retry it if it fails. WSProvider holds it until the server echoes the message back, and ChatModal shows it, as PendingItem, after the messages the server has.","url":"./src/contexts/ws/WSContext.ts/~/PendingChatMessage.html","deprecated":false},{"id":"namespace_pendingchatmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PendingChatMessage.nonce","file":"src/contexts/ws/WSContext.ts","doc":"Sent with chat_send and returned with the echo or the error. A retry gets a new one, so a late echo of the first attempt can't retire it.","url":"./src/contexts/ws/WSContext.ts/~/PendingChatMessage.nonce.html","deprecated":false},{"id":"namespace_pendingchatmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PendingChatMessage.body","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/PendingChatMessage.body.html","deprecated":false},{"id":"namespace_pendingchatmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PendingChatMessage.replyTo","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/PendingChatMessage.replyTo.html","deprecated":false},{"id":"namespace_pendingchatmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PendingChatMessage.createdAt","file":"src/contexts/ws/WSContext.ts","doc":"When this client sent it, to find it in the history after a reconnect.","url":"./src/contexts/ws/WSContext.ts/~/PendingChatMessage.createdAt.html","deprecated":false},{"id":"namespace_pendingchatmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PendingChatMessage.status","file":"src/contexts/ws/WSContext.ts","doc":"failed when the server refused it, the socket was down or closed, or no echo came in 10 s. A failed message may still have reached the server.","url":"./src/contexts/ws/WSContext.ts/~/PendingChatMessage.status.html","deprecated":false},{"id":"namespace_pendingchatmessage","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PendingChatMessage.error","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/PendingChatMessage.error.html","deprecated":false},{"id":"namespace_chaterror","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ChatError","file":"src/contexts/ws/WSContext.ts","doc":"Tells the user the server refused their chat edit or delete. WSProvider sets it as chatError, and ChatModal shows it for a few seconds.","url":"./src/contexts/ws/WSContext.ts/~/ChatError.html","deprecated":false},{"id":"namespace_chaterror","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatError.id","file":"src/contexts/ws/WSContext.ts","doc":"Tells apart two errors with the same message.","url":"./src/contexts/ws/WSContext.ts/~/ChatError.id.html","deprecated":false},{"id":"namespace_chaterror","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ChatError.message","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/ChatError.message.html","deprecated":false},{"id":"namespace_wscontextvalue","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"WSContextValue","file":"src/contexts/ws/WSContext.ts","doc":"Carries the live state but the chat and presence, for pages to lay over what they fetched. WSProvider provides it through WSContext, and components read it with useWS. The changes to single items come as events instead, through WSEventsContext. After a reconnect, connectionEpoch tells pages to fetch what they missed.","url":"./src/contexts/ws/WSContext.ts/~/WSContextValue.html","deprecated":false},{"id":"namespace_wscontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSContextValue.wsStatus","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/WSContextValue.wsStatus.html","deprecated":false},{"id":"namespace_wscontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSContextValue.wsErrorMessage","file":"src/contexts/ws/WSContext.ts","doc":"Set while the socket is down, for the banner that says so.","url":"./src/contexts/ws/WSContext.ts/~/WSContextValue.wsErrorMessage.html","deprecated":false},{"id":"namespace_wscontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSContextValue.voteCounts","file":"src/contexts/ws/WSContext.ts","doc":"Shows vote counts live. It holds, by dump id, the counts the server pushed or this tab changed optimistically; a dump missing from it shows its fetched voteCount.","url":"./src/contexts/ws/WSContext.ts/~/WSContextValue.voteCounts.html","deprecated":false},{"id":"namespace_wscontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSContextValue.myVotes","file":"src/contexts/ws/WSContext.ts","doc":"Marks the dumps this user upvoted, for their vote buttons. The server's welcome resets it on every connection.","url":"./src/contexts/ws/WSContext.ts/~/WSContextValue.myVotes.html","deprecated":false},{"id":"namespace_wscontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSContextValue.likeCounts","file":"src/contexts/ws/WSContext.ts","doc":"As voteCounts, for comments.","url":"./src/contexts/ws/WSContext.ts/~/WSContextValue.likeCounts.html","deprecated":false},{"id":"namespace_wscontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSContextValue.myLikes","file":"src/contexts/ws/WSContext.ts","doc":"As myVotes, for comments.","url":"./src/contexts/ws/WSContext.ts/~/WSContextValue.myLikes.html","deprecated":false},{"id":"namespace_wscontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSContextValue.recentDumps","file":"src/contexts/ws/WSContext.ts","doc":"Shows new dumps on the index as they are posted, merged by date with the feed Index fetched. It holds, newest first and at most 100, the ones the server announced this session, which are public, and the ones this user posted, which may be private.","url":"./src/contexts/ws/WSContext.ts/~/WSContextValue.recentDumps.html","deprecated":false},{"id":"namespace_wscontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSContextValue.deletedDumpIds","file":"src/contexts/ws/WSContext.ts","doc":"Takes deleted dumps off every list at once. It holds the dumps deleted this session, or made private by someone else; a dump made public again leaves it.","url":"./src/contexts/ws/WSContext.ts/~/WSContextValue.deletedDumpIds.html","deprecated":false},{"id":"namespace_wscontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSContextValue.deletedPlaylistIds","file":"src/contexts/ws/WSContext.ts","doc":"Takes deleted playlists off every list at once, as deletedDumpIds does dumps.","url":"./src/contexts/ws/WSContext.ts/~/WSContextValue.deletedPlaylistIds.html","deprecated":false},{"id":"namespace_wscontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSContextValue.unreadNotificationCount","file":"src/contexts/ws/WSContext.ts","doc":"Drives the bell's badge. It comes from the welcome, then each new notification counts it up, and notifications_read zeroes it.","url":"./src/contexts/ws/WSContext.ts/~/WSContextValue.unreadNotificationCount.html","deprecated":false},{"id":"namespace_wscontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSContextValue.connectionEpoch","file":"src/contexts/ws/WSContext.ts","doc":"Tells pages to fetch again what they missed while the socket was down. It goes up on each reconnect, never on the first connection.","url":"./src/contexts/ws/WSContext.ts/~/WSContextValue.connectionEpoch.html","deprecated":false},{"id":"namespace_wscontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSContextValue.followsVersion","file":"src/contexts/ws/WSContext.ts","doc":"Keeps the Follow buttons right when the user follows or unfollows in another tab. It goes up on every follow change, in any tab, and FollowProvider fetches the follow status again.","url":"./src/contexts/ws/WSContext.ts/~/WSContextValue.followsVersion.html","deprecated":false},{"id":"namespace_wscontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSContextValue.castVote","file":"src/contexts/ws/WSContext.ts","doc":"Upvotes a dump at once and sends vote_cast. The server's answer confirms or reverts it, and so does a timeout of 5 s, which covers a closed socket. shownCount is the count on screen, used when voteCounts has none yet. Does nothing when the user already voted.","url":"./src/contexts/ws/WSContext.ts/~/WSContextValue.castVote.html","deprecated":false},{"id":"namespace_wscontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSContextValue.removeVote","file":"src/contexts/ws/WSContext.ts","doc":"Withdraws an upvote, as WSContextValue.castVote casts one.","url":"./src/contexts/ws/WSContext.ts/~/WSContextValue.removeVote.html","deprecated":false},{"id":"namespace_wscontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSContextValue.castCommentLike","file":"src/contexts/ws/WSContext.ts","doc":"Likes a comment, as WSContextValue.castVote upvotes a dump.","url":"./src/contexts/ws/WSContext.ts/~/WSContextValue.castCommentLike.html","deprecated":false},{"id":"namespace_wscontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSContextValue.removeCommentLike","file":"src/contexts/ws/WSContext.ts","doc":"Withdraws a like, as WSContextValue.castVote casts a vote.","url":"./src/contexts/ws/WSContext.ts/~/WSContextValue.removeCommentLike.html","deprecated":false},{"id":"namespace_wscontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSContextValue.injectDump","file":"src/contexts/ws/WSContext.ts","doc":"Shows a dump this user just posted on the index without waiting for its broadcast. DumpCreateModal calls it, and it adds the dump to recentDumps.","url":"./src/contexts/ws/WSContext.ts/~/WSContextValue.injectDump.html","deprecated":false},{"id":"namespace_wscontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSContextValue.clearUnreadNotifications","file":"src/contexts/ws/WSContext.ts","doc":"Zeroes the bell's count, once the notifications page has marked them read on the server.","url":"./src/contexts/ws/WSContext.ts/~/WSContextValue.clearUnreadNotifications.html","deprecated":false},{"id":"namespace_wschatcontextvalue","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"WSChatContextValue","file":"src/contexts/ws/WSContext.ts","doc":"Carries the chat's live side, which ChatModal lays over the history it fetches and the chat buttons show as a badge. WSProvider provides it through WSChatContext, and components read it with useWSChat. The socket sends chat only to signed-in users, so for a visitor it stays empty.","url":"./src/contexts/ws/WSContext.ts/~/WSChatContextValue.html","deprecated":false},{"id":"namespace_wschatcontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSChatContextValue.chatMessages","file":"src/contexts/ws/WSContext.ts","doc":"Shows chat messages as they arrive. It holds the ones received this session, at most 200, which ChatModal merges with the history it fetches. A reconnect empties it while the chat is closed, since ChatModal fetches everything again on open.","url":"./src/contexts/ws/WSContext.ts/~/WSChatContextValue.chatMessages.html","deprecated":false},{"id":"namespace_wschatcontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSChatContextValue.deletedChatIds","file":"src/contexts/ws/WSContext.ts","doc":"Takes the messages deleted this session out of the history ChatModal fetched.","url":"./src/contexts/ws/WSContext.ts/~/WSChatContextValue.deletedChatIds.html","deprecated":false},{"id":"namespace_wschatcontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSChatContextValue.unreadChatCount","file":"src/contexts/ws/WSContext.ts","doc":"Drives the chat buttons' unread badge. It counts the messages from others after the read marker, which the server keeps, so the count agrees across tabs and devices.","url":"./src/contexts/ws/WSContext.ts/~/WSChatContextValue.unreadChatCount.html","deprecated":false},{"id":"namespace_wschatcontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSChatContextValue.chatReadAt","file":"src/contexts/ws/WSContext.ts","doc":"Places the \"new\" divider when the chat opens. It holds the time of the newest message the user has seen, which the server keeps, and is null until the welcome, and for a visitor.","url":"./src/contexts/ws/WSContext.ts/~/WSChatContextValue.chatReadAt.html","deprecated":false},{"id":"namespace_wschatcontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSChatContextValue.pendingChatMessages","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/WSChatContextValue.pendingChatMessages.html","deprecated":false},{"id":"namespace_wschatcontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSChatContextValue.chatError","file":"src/contexts/ws/WSContext.ts","doc":"Only for edits and deletes. A failed send shows on its pending message.","url":"./src/contexts/ws/WSContext.ts/~/WSChatContextValue.chatError.html","deprecated":false},{"id":"namespace_wschatcontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSChatContextValue.typingUsers","file":"src/contexts/ws/WSContext.ts","doc":"Shows who is typing. It includes the user themselves, whom ChatModal filters out.","url":"./src/contexts/ws/WSContext.ts/~/WSChatContextValue.typingUsers.html","deprecated":false},{"id":"namespace_wschatcontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSChatContextValue.sendChatMessage","file":"src/contexts/ws/WSContext.ts","doc":"Trims body and sends it as a pending message. Ignores a blank body.","url":"./src/contexts/ws/WSContext.ts/~/WSChatContextValue.sendChatMessage.html","deprecated":false},{"id":"namespace_wschatcontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSChatContextValue.retryChatMessage","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/WSChatContextValue.retryChatMessage.html","deprecated":false},{"id":"namespace_wschatcontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSChatContextValue.discardChatMessage","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/WSChatContextValue.discardChatMessage.html","deprecated":false},{"id":"namespace_wschatcontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSChatContextValue.editChatMessage","file":"src/contexts/ws/WSContext.ts","doc":"Sends the edit if the socket is open, else drops it. It shows once the server broadcasts it, or fails as chatError.","url":"./src/contexts/ws/WSContext.ts/~/WSChatContextValue.editChatMessage.html","deprecated":false},{"id":"namespace_wschatcontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSChatContextValue.deleteChatMessage","file":"src/contexts/ws/WSContext.ts","doc":"Sends the deletion if the socket is open, as editChatMessage does.","url":"./src/contexts/ws/WSContext.ts/~/WSChatContextValue.deleteChatMessage.html","deprecated":false},{"id":"namespace_wschatcontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSChatContextValue.dismissChatError","file":"src/contexts/ws/WSContext.ts","doc":"","url":"./src/contexts/ws/WSContext.ts/~/WSChatContextValue.dismissChatError.html","deprecated":false},{"id":"namespace_wschatcontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSChatContextValue.markChatRead","file":"src/contexts/ws/WSContext.ts","doc":"Moves the read marker up to at, the time of the newest message seen. It zeroes unreadChatCount at once and sends the marker at most once a second. A marker set offline goes out with the next welcome.","url":"./src/contexts/ws/WSContext.ts/~/WSChatContextValue.markChatRead.html","deprecated":false},{"id":"namespace_wschatcontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSChatContextValue.reconcileChat","file":"src/contexts/ws/WSContext.ts","doc":"Repairs the live buffer after a reconnect. It replaces its messages between from and to with messages, which ChatModal fetched. A message missing from them was deleted while the socket was down. A failed send found among them did reach the server, and leaves the pending list.","url":"./src/contexts/ws/WSContext.ts/~/WSChatContextValue.reconcileChat.html","deprecated":false},{"id":"namespace_wschatcontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSChatContextValue.setChatTyping","file":"src/contexts/ws/WSContext.ts","doc":"Tells the server whether the user is typing, when the socket is open. ChatModal resends true every few seconds while typing continues, since the server forgets a typer after 6 s.","url":"./src/contexts/ws/WSContext.ts/~/WSChatContextValue.setChatTyping.html","deprecated":false},{"id":"namespace_wschatcontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSChatContextValue.setChatOpen","file":"src/contexts/ws/WSContext.ts","doc":"Spares the user a notification for a mention they read live. It tells the server whether the chat is open in a visible tab; while it is, the server sends no notification for a mention, and this client doesn't count the message unread.","url":"./src/contexts/ws/WSContext.ts/~/WSChatContextValue.setChatOpen.html","deprecated":false},{"id":"namespace_wspresencecontextvalue","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"WSPresenceContextValue","file":"src/contexts/ws/WSContext.ts","doc":"Carries who is online, for PresenceRow. WSProvider provides it through WSPresenceContext, and components read it with useWSPresence.","url":"./src/contexts/ws/WSContext.ts/~/WSPresenceContextValue.html","deprecated":false},{"id":"namespace_wspresencecontextvalue","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSPresenceContextValue.onlineUsers","file":"src/contexts/ws/WSContext.ts","doc":"The signed-in users with a socket open, each once.","url":"./src/contexts/ws/WSContext.ts/~/WSPresenceContextValue.onlineUsers.html","deprecated":false},{"id":"namespace_defaultwsvalue","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"defaultWSValue","file":"src/contexts/ws/WSContext.ts","doc":"Lets a component render outside WSProvider, as if the socket were connecting.","url":"./src/contexts/ws/WSContext.ts/~/defaultWSValue.html","deprecated":false},{"id":"namespace_defaultwschatvalue","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"defaultWSChatValue","file":"src/contexts/ws/WSContext.ts","doc":"Lets a component render outside WSProvider, with an empty chat.","url":"./src/contexts/ws/WSContext.ts/~/defaultWSChatValue.html","deprecated":false},{"id":"namespace_defaultwspresencevalue","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"defaultWSPresenceValue","file":"src/contexts/ws/WSContext.ts","doc":"Lets a component render outside WSProvider, with nobody online.","url":"./src/contexts/ws/WSContext.ts/~/defaultWSPresenceValue.html","deprecated":false},{"id":"namespace_wscontext","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"WSContext","file":"src/contexts/ws/WSContext.ts","doc":"Carries the live state pages lay over what they fetched: the connection, the votes and likes, and the latest event of each kind. Read it with useWS.","url":"./src/contexts/ws/WSContext.ts/~/WSContext.html","deprecated":false},{"id":"namespace_wschatcontext","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"WSChatContext","file":"src/contexts/ws/WSContext.ts","doc":"Carries the chat's live stream and read state. Read it with useWSChat.","url":"./src/contexts/ws/WSContext.ts/~/WSChatContext.html","deprecated":false},{"id":"namespace_wspresencecontext","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"WSPresenceContext","file":"src/contexts/ws/WSContext.ts","doc":"Carries who is online. Read it with useWSPresence.","url":"./src/contexts/ws/WSContext.ts/~/WSPresenceContext.html","deprecated":false},{"id":"namespace_wseventscontext","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"WSEventsContext","file":"src/contexts/ws/WSContext.ts","doc":"Carries the bus WSProvider emits its events on, for useWSEvent. Outside WSProvider, it is a bus no one emits on.","url":"./src/contexts/ws/WSContext.ts/~/WSEventsContext.html","deprecated":false},{"id":"namespace_wsproviderprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"WSProviderProps","file":"src/contexts/ws/WSProvider.tsx","doc":"Passed to WSProvider by App.","url":"./src/contexts/ws/WSProvider.tsx/~/WSProviderProps.html","deprecated":false},{"id":"namespace_wsproviderprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"WSProviderProps.children","file":"src/contexts/ws/WSProvider.tsx","doc":"","url":"./src/contexts/ws/WSProvider.tsx/~/WSProviderProps.children.html","deprecated":false},{"id":"namespace_wsprovider","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"WSProvider","file":"src/contexts/ws/WSProvider.tsx","doc":"Provides WSContext, WSChatContext, WSPresenceContext, AvatarOverrideContext and WSEventsContext. It connects with the session's token, or anonymously, and reconnects with a backoff doubling up to 30 s. A new token (sign-in, sign-out, another account) clears the live state and reconnects. A new notification or chat message chimes, and the unread counts go in the tab title.","url":"./src/contexts/ws/WSProvider.tsx/~/WSProvider.html","deprecated":false},{"id":"namespace_useauthresult","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UseAuthResult","file":"src/hooks/auth/useAuth.ts","doc":"Returned by useAuth to any component that needs the session. Its functions are stable until the session's token changes.","url":"./src/hooks/auth/useAuth.ts/~/UseAuthResult.html","deprecated":false},{"id":"namespace_useauthresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseAuthResult.user","file":"src/hooks/auth/useAuth.ts","doc":"","url":"./src/hooks/auth/useAuth.ts/~/UseAuthResult.user.html","deprecated":false},{"id":"namespace_useauthresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseAuthResult.settings","file":"src/hooks/auth/useAuth.ts","doc":"The user's settings, once AuthProvider has read them. useSettings is the way to read and change them.","url":"./src/hooks/auth/useAuth.ts/~/UseAuthResult.settings.html","deprecated":false},{"id":"namespace_useauthresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseAuthResult.token","file":"src/hooks/auth/useAuth.ts","doc":"","url":"./src/hooks/auth/useAuth.ts/~/UseAuthResult.token.html","deprecated":false},{"id":"namespace_useauthresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseAuthResult.mediaToken","file":"src/hooks/auth/useAuth.ts","doc":"The token for file and thumbnail URLs, where it shows in the query string. A session from before media tokens falls back to the session token until AuthProvider fetches one.","url":"./src/hooks/auth/useAuth.ts/~/UseAuthResult.mediaToken.html","deprecated":false},{"id":"namespace_useauthresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseAuthResult.login","file":"src/hooks/auth/useAuth.ts","doc":"Starts a session from a sign-in or sign-up response, in every tab.","url":"./src/hooks/auth/useAuth.ts/~/UseAuthResult.login.html","deprecated":false},{"id":"namespace_useauthresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseAuthResult.logout","file":"src/hooks/auth/useAuth.ts","doc":"Ends the session this render holds. A 401 can land after the session has moved on to fresh tokens (a password change, here or in another tab), and must not sign those out.","url":"./src/hooks/auth/useAuth.ts/~/UseAuthResult.logout.html","deprecated":false},{"id":"namespace_useauthresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseAuthResult.updateSession","file":"src/hooks/auth/useAuth.ts","doc":"Merges patch into the session, in memory and in storage. The profile page uses it for a new avatar or email, the password dialog for fresh tokens.","url":"./src/hooks/auth/useAuth.ts/~/UseAuthResult.updateSession.html","deprecated":false},{"id":"namespace_useauthresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseAuthResult.authFetch","file":"src/hooks/auth/useAuth.ts","doc":"Calls fetch with the session's token, and a JSON content type unless the body is FormData. An expired token, or a 401, ends the session. An expired token answers a 401 without calling the server.","url":"./src/hooks/auth/useAuth.ts/~/UseAuthResult.authFetch.html","deprecated":false},{"id":"namespace_useauthresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseAuthResult.authUpload","file":"src/hooks/auth/useAuth.ts","doc":"Works like authFetch for a multipart upload that shows progress, as the dump creation dialog's file upload does. It goes through XHR, since fetch reports nothing until the whole body is sent. It still answers a Response, so callers use expectOk as usual.onProgress receives a fraction from 0 to 1, or null once the body is sent and the server is working, or when the length is unknown.","url":"./src/hooks/auth/useAuth.ts/~/UseAuthResult.authUpload.html","deprecated":false},{"id":"namespace_useauth","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useAuth","file":"src/hooks/auth/useAuth.ts","doc":"Returns the session and the functions that act on it. It must be called under AuthProvider.","url":"./src/hooks/auth/useAuth.ts/~/useAuth.html","deprecated":false},{"id":"namespace_userequiredauthresult","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UseRequiredAuthResult","file":"src/hooks/auth/useAuth.ts","doc":"Returned by useRequiredAuth. It is UseAuthResult with a user that can't be null.","url":"./src/hooks/auth/useAuth.ts/~/UseRequiredAuthResult.html","deprecated":false},{"id":"namespace_userequiredauthresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseRequiredAuthResult.user","file":"src/hooks/auth/useAuth.ts","doc":"","url":"./src/hooks/auth/useAuth.ts/~/UseRequiredAuthResult.user.html","deprecated":false},{"id":"namespace_userequiredauth","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useRequiredAuth","file":"src/hooks/auth/useAuth.ts","doc":"Returns the session, for a page that RestrictedLoggedIn guards, such as DumpEdit, so it needn't check for a user.","url":"./src/hooks/auth/useAuth.ts/~/useRequiredAuth.html","deprecated":false},{"id":"namespace_usesettingsresult","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UseSettingsResult","file":"src/hooks/auth/useSettings.ts","doc":"Returned by useSettings to whatever reads or changes settings.","url":"./src/hooks/auth/useSettings.ts/~/UseSettingsResult.html","deprecated":false},{"id":"namespace_usesettingsresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseSettingsResult.settings","file":"src/hooks/auth/useSettings.ts","doc":"The settings, or null when signed out or before AuthProvider has read them from the server.","url":"./src/hooks/auth/useSettings.ts/~/UseSettingsResult.settings.html","deprecated":false},{"id":"namespace_usesettingsresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseSettingsResult.updateSettings","file":"src/hooks/auth/useSettings.ts","doc":"Applies patch at once, then saves it with PATCH /api/me/settings. A refusal puts the previous settings back and throws.","url":"./src/hooks/auth/useSettings.ts/~/UseSettingsResult.updateSettings.html","deprecated":false},{"id":"namespace_usesettings","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useSettings","file":"src/hooks/auth/useSettings.ts","doc":"Returns the settings and their setter. It must be called under AuthProvider.","url":"./src/hooks/auth/useSettings.ts/~/useSettings.html","deprecated":false},{"id":"namespace_kindcategories","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"KindCategories","file":"src/hooks/category/useCategories.ts","doc":"Returned by useCategories: one kind's categories.","url":"./src/hooks/category/useCategories.ts/~/KindCategories.html","deprecated":false},{"id":"namespace_kindcategories","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"KindCategories.categories","file":"src/hooks/category/useCategories.ts","doc":"The categories of the kind, by position then slug.","url":"./src/hooks/category/useCategories.ts/~/KindCategories.categories.html","deprecated":false},{"id":"namespace_kindcategories","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"KindCategories.byId","file":"src/hooks/category/useCategories.ts","doc":"Resolves a dump's or playlist's categoryIds to its category chips.","url":"./src/hooks/category/useCategories.ts/~/KindCategories.byId.html","deprecated":false},{"id":"namespace_kindcategories","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"KindCategories.isLoaded","file":"src/hooks/category/useCategories.ts","doc":"Whether the first fetch has ended. It is also true after a network error, with no categories.","url":"./src/hooks/category/useCategories.ts/~/KindCategories.isLoaded.html","deprecated":false},{"id":"namespace_kindcategories","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"KindCategories.refresh","file":"src/hooks/category/useCategories.ts","doc":"Refetches both kinds. The category manager calls it after each change.","url":"./src/hooks/category/useCategories.ts/~/KindCategories.refresh.html","deprecated":false},{"id":"namespace_usecategories","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useCategories","file":"src/hooks/category/useCategories.ts","doc":"Returns the categories of kind, dump or playlist, and a function that refetches them. Under no CategoriesProvider, the list is empty.","url":"./src/hooks/category/useCategories.ts/~/useCategories.html","deprecated":false},{"id":"namespace_usecategoryfilter","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useCategoryFilter","file":"src/hooks/category/useCategoryFilter.ts","doc":"Returns setItems wrapped so that every list it sets keeps only the items filed under categoryId, or setItems as it is without one. A list of one category's dumps or playlists passes it to the hooks that apply the socket's messages, so that one created outside the category isn't added, and one edited out of it leaves.","url":"./src/hooks/category/useCategoryFilter.ts/~/useCategoryFilter.html","deprecated":false},{"id":"namespace_usecategoryselection","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useCategorySelection","file":"src/hooks/category/useCategorySelection.ts","doc":"Returns the ids picked, starting from initial, a function that turns one on or off, and one that replaces them all. The dump creation dialog, the dump editor and the playlist forms send [...selected] as categoryIds.","url":"./src/hooks/category/useCategorySelection.ts/~/useCategorySelection.html","deprecated":false},{"id":"namespace_usechat","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useChat","file":"src/hooks/chat/useChat.ts","doc":"Returns the chat modal's open state, and the functions that open and close it. Needs ChatProvider above, which App mounts around every page.","url":"./src/hooks/chat/useChat.ts/~/useChat.html","deprecated":false},{"id":"namespace_usedumpcardlink","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useDumpCardLink","file":"src/hooks/dump/useDumpCardLink.ts","doc":"Returns useCardLink's handlers for the card of dump, for DumpCard and JournalCard: every way they open the dump marks it visited, which clears its unread dot.","url":"./src/hooks/dump/useDumpCardLink.ts/~/useDumpCardLink.html","deprecated":false},{"id":"namespace_dumplistsyncoptions","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"DumpListSyncOptions","file":"src/hooks/dump/useDumpListSync.ts","doc":"Passed to useDumpListSync by the lists that need more than edits and deletions.","url":"./src/hooks/dump/useDumpListSync.ts/~/DumpListSyncOptions.html","deprecated":false},{"id":"namespace_dumplistsyncoptions","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpListSyncOptions.isOwner","file":"src/hooks/dump/useDumpListSync.ts","doc":"The list holds the viewer's own private dumps, as their profile, the index and the search do, so that one they make private stays. Only its poster hears of a private dump's edits.","url":"./src/hooks/dump/useDumpListSync.ts/~/DumpListSyncOptions.isOwner.html","deprecated":false},{"id":"namespace_dumplistsyncoptions","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpListSyncOptions.belongs","file":"src/hooks/dump/useDumpListSync.ts","doc":"Which dumps the list may hold. A dump that left it, as by turning private, comes back where it was when it returns and this accepts it. Without it, the list never gains a dump.","url":"./src/hooks/dump/useDumpListSync.ts/~/DumpListSyncOptions.belongs.html","deprecated":false},{"id":"namespace_dumplistsyncoptions","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpListSyncOptions.addNew","file":"src/hooks/dump/useDumpListSync.ts","doc":"Also adds a dump belongs accepts that the list never held, where the newest-first order puts it among the dumps loaded: a new one first. One older than all of them is left to the next pages. For the lists sorted by createdAt: the index's feed, a profile's dumps, the followed users'.","url":"./src/hooks/dump/useDumpListSync.ts/~/DumpListSyncOptions.addNew.html","deprecated":false},{"id":"namespace_usedumplistsync","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useDumpListSync","file":"src/hooks/dump/useDumpListSync.ts","doc":"Applies the socket's dump, comment and user events to items, the loaded list, which setDumps updates. A deleted dump is removed, an edited one is replaced in place, one gone private leaves unless isOwner, and a new or returning one is added as belongs and addNew say. A new or deleted comment moves its dump's commentCount, and a renamed user's dumps take their new name.","url":"./src/hooks/dump/useDumpListSync.ts/~/useDumpListSync.html","deprecated":false},{"id":"namespace_useupvotedlistoptions","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UseUpvotedListOptions","file":"src/hooks/dump/useUpvotedList.ts","doc":"Passed to useUpvotedList by useUserDumpFeed, for an upvoted list.","url":"./src/hooks/dump/useUpvotedList.ts/~/UseUpvotedListOptions.html","deprecated":false},{"id":"namespace_useupvotedlistoptions","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseUpvotedListOptions.profileUserId","file":"src/hooks/dump/useUpvotedList.ts","doc":"The list holds this user's upvotes. It is null while their profile loads.","url":"./src/hooks/dump/useUpvotedList.ts/~/UseUpvotedListOptions.profileUserId.html","deprecated":false},{"id":"namespace_useupvotedlistoptions","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseUpvotedListOptions.setItems","file":"src/hooks/dump/useUpvotedList.ts","doc":"Does nothing until the list is loaded.","url":"./src/hooks/dump/useUpvotedList.ts/~/UseUpvotedListOptions.setItems.html","deprecated":false},{"id":"namespace_useupvotedlistoptions","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseUpvotedListOptions.source","file":"src/hooks/dump/useUpvotedList.ts","doc":"It holds dumps already at hand, which a vote of the signed-in user on their own list puts first at once, before the socket's vote event. The profile passes its first page of the user's dumps.","url":"./src/hooks/dump/useUpvotedList.ts/~/UseUpvotedListOptions.source.html","deprecated":false},{"id":"namespace_useupvotedlistresult","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UseUpvotedListResult","file":"src/hooks/dump/useUpvotedList.ts","doc":"Returned by useUpvotedList.","url":"./src/hooks/dump/useUpvotedList.ts/~/UseUpvotedListResult.html","deprecated":false},{"id":"namespace_useupvotedlistresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseUpvotedListResult.cardClassName","file":"src/hooks/dump/useUpvotedList.ts","doc":"It goes to DumpCardList's cardClassName.","url":"./src/hooks/dump/useUpvotedList.ts/~/UseUpvotedListResult.cardClassName.html","deprecated":false},{"id":"namespace_useupvotedlistresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseUpvotedListResult.isWithdrawn","file":"src/hooks/dump/useUpvotedList.ts","doc":"Checks whether the vote on dump id was withdrawn since the list loaded. The profile's useDumpListSync keeps such a dump from coming back.","url":"./src/hooks/dump/useUpvotedList.ts/~/UseUpvotedListResult.isWithdrawn.html","deprecated":false},{"id":"namespace_useupvotedlist","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useUpvotedList","file":"src/hooks/dump/useUpvotedList.ts","doc":"Follows the votes of profileUserId into their upvoted list. A dump they upvote is fetched and put first. One whose vote they withdraw fades out (useFading), then leaves the list, unless they vote again meanwhile. The socket's vote events report every browser's votes; on one's own list, myVotes also reports this tab's at once.","url":"./src/hooks/dump/useUpvotedList.ts/~/useUpvotedList.html","deprecated":false},{"id":"namespace_userdumplist","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"UserDumpList","file":"src/hooks/dump/useUserDumpFeed.ts","doc":"One of a profile's lists of dumps, a path segment of its API and page.","url":"./src/hooks/dump/useUserDumpFeed.ts/~/UserDumpList.html","deprecated":false},{"id":"namespace_useuserdumpfeedresult","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UseUserDumpFeedResult","file":"src/hooks/dump/useUserDumpFeed.ts","doc":"Returned by useUserDumpFeed.","url":"./src/hooks/dump/useUserDumpFeed.ts/~/UseUserDumpFeedResult.html","deprecated":false},{"id":"namespace_useuserdumpfeedresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseUserDumpFeedResult.cardClassName","file":"src/hooks/dump/useUserDumpFeed.ts","doc":"It goes to the list's DumpCardList: on the upvoted list, it fades out a withdrawn upvote.","url":"./src/hooks/dump/useUserDumpFeed.ts/~/UseUserDumpFeedResult.cardClassName.html","deprecated":false},{"id":"namespace_useuserdumpfeedoptions","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UseUserDumpFeedOptions","file":"src/hooks/dump/useUserDumpFeed.ts","doc":"Passed to useUserDumpFeed by the profile's overview and tabs.","url":"./src/hooks/dump/useUserDumpFeed.ts/~/UseUserDumpFeedOptions.html","deprecated":false},{"id":"namespace_useuserdumpfeedoptions","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseUserDumpFeedOptions.isOwner","file":"src/hooks/dump/useUserDumpFeed.ts","doc":"Keeps the user's own private dumps in their list as they edit them.","url":"./src/hooks/dump/useUserDumpFeed.ts/~/UseUserDumpFeedOptions.isOwner.html","deprecated":false},{"id":"namespace_useuserdumpfeedoptions","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseUserDumpFeedOptions.source","file":"src/hooks/dump/useUserDumpFeed.ts","doc":"Dumps at hand that a vote of the user's own puts first in their upvoted.","url":"./src/hooks/dump/useUserDumpFeed.ts/~/UseUserDumpFeedOptions.source.html","deprecated":false},{"id":"namespace_useuserdumpfeedoptions","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseUserDumpFeedOptions.categorySlug","file":"src/hooks/dump/useUserDumpFeed.ts","doc":"Narrows the list to the category at this slug.","url":"./src/hooks/dump/useUserDumpFeed.ts/~/UseUserDumpFeedOptions.categorySlug.html","deprecated":false},{"id":"namespace_useuserdumpfeed","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useUserDumpFeed","file":"src/hooks/dump/useUserDumpFeed.ts","doc":"Returns list of user userId, from GET /api/users/:userId/<list>, fetched signed in so users see their own private dumps, with the call that loads its next page; with categorySlug, only the dumps in that category. The socket keeps it live: the user's new dumps come in, a dump that goes private and public again comes back at its place, one edited out of the category leaves, one edited into it comes in, and the upvoted list follows the user's votes, source holding dumps at hand that a vote of theirs puts first at once. A reconnection fetches the pages loaded again. The list and the scroll position are saved as the page is left, under a key the overview and the unfiltered tab share, and going back restores them.","url":"./src/hooks/dump/useUserDumpFeed.ts/~/useUserDumpFeed.html","deprecated":false},{"id":"namespace_emojimode","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"EmojiMode","file":"src/hooks/editor/useEmojiTrigger.ts","doc":"Returned by useEmojiTrigger to TextEditor, which keys its focus and key handling on it. An inline picker was opened by a typed :query: focus stays in the textarea and a pick replaces the query. A browse picker was opened from the button: focus goes to its search and a pick lands at the caret.","url":"./src/hooks/editor/useEmojiTrigger.ts/~/EmojiMode.html","deprecated":false},{"id":"namespace_useemojitriggerresult","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UseEmojiTriggerResult","file":"src/hooks/editor/useEmojiTrigger.ts","doc":"Returned by useEmojiTrigger to TextEditor.","url":"./src/hooks/editor/useEmojiTrigger.ts/~/UseEmojiTriggerResult.html","deprecated":false},{"id":"namespace_useemojitriggerresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseEmojiTriggerResult.emojiMode","file":"src/hooks/editor/useEmojiTrigger.ts","doc":"","url":"./src/hooks/editor/useEmojiTrigger.ts/~/UseEmojiTriggerResult.emojiMode.html","deprecated":false},{"id":"namespace_useemojitriggerresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseEmojiTriggerResult.emojiQuery","file":"src/hooks/editor/useEmojiTrigger.ts","doc":"","url":"./src/hooks/editor/useEmojiTrigger.ts/~/UseEmojiTriggerResult.emojiQuery.html","deprecated":false},{"id":"namespace_useemojitriggerresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseEmojiTriggerResult.syncEmojiTrigger","file":"src/hooks/editor/useEmojiTrigger.ts","doc":"Follows an inline :query and closes the picker once the caret leaves it. The caller calls it on every change with open set, and on every caret move without, since only typing may open the picker. It leaves a browse picker alone.","url":"./src/hooks/editor/useEmojiTrigger.ts/~/UseEmojiTriggerResult.syncEmojiTrigger.html","deprecated":false},{"id":"namespace_useemojitriggerresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseEmojiTriggerResult.openEmojiBrowser","file":"src/hooks/editor/useEmojiTrigger.ts","doc":"Opens a browse picker, whose pick will replace [start, end).","url":"./src/hooks/editor/useEmojiTrigger.ts/~/UseEmojiTriggerResult.openEmojiBrowser.html","deprecated":false},{"id":"namespace_useemojitriggerresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseEmojiTriggerResult.setEmojiQuery","file":"src/hooks/editor/useEmojiTrigger.ts","doc":"Sets the query of the picker's search, in either mode.","url":"./src/hooks/editor/useEmojiTrigger.ts/~/UseEmojiTriggerResult.setEmojiQuery.html","deprecated":false},{"id":"namespace_useemojitriggerresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseEmojiTriggerResult.selectEmoji","file":"src/hooks/editor/useEmojiTrigger.ts","doc":"Inserts the emoji native through replace and closes the picker.","url":"./src/hooks/editor/useEmojiTrigger.ts/~/UseEmojiTriggerResult.selectEmoji.html","deprecated":false},{"id":"namespace_useemojitriggerresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseEmojiTriggerResult.closeEmoji","file":"src/hooks/editor/useEmojiTrigger.ts","doc":"","url":"./src/hooks/editor/useEmojiTrigger.ts/~/UseEmojiTriggerResult.closeEmoji.html","deprecated":false},{"id":"namespace_useemojitrigger","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useEmojiTrigger","file":"src/hooks/editor/useEmojiTrigger.ts","doc":"Returns the picker's state and the functions that drive it. A pick goes through replace, TextEditor's function that puts the text over [start, end) of the textarea's value, followed by a space when word is set.","url":"./src/hooks/editor/useEmojiTrigger.ts/~/useEmojiTrigger.html","deprecated":false},{"id":"namespace_mentionkey","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"MentionKey","file":"src/hooks/editor/useMentionAutocomplete.ts","doc":"Passed to UseMentionAutocompleteResult.handleMentionKeyDown by TextEditor. It is the part of a React keydown event that the list reads.","url":"./src/hooks/editor/useMentionAutocomplete.ts/~/MentionKey.html","deprecated":false},{"id":"namespace_usementionautocompleteresult","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UseMentionAutocompleteResult","file":"src/hooks/editor/useMentionAutocomplete.ts","doc":"Returned by useMentionAutocomplete to TextEditor.","url":"./src/hooks/editor/useMentionAutocomplete.ts/~/UseMentionAutocompleteResult.html","deprecated":false},{"id":"namespace_usementionautocompleteresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseMentionAutocompleteResult.mentionOpen","file":"src/hooks/editor/useMentionAutocomplete.ts","doc":"Set only once a search has found someone.","url":"./src/hooks/editor/useMentionAutocomplete.ts/~/UseMentionAutocompleteResult.mentionOpen.html","deprecated":false},{"id":"namespace_usementionautocompleteresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseMentionAutocompleteResult.mentionResults","file":"src/hooks/editor/useMentionAutocomplete.ts","doc":"","url":"./src/hooks/editor/useMentionAutocomplete.ts/~/UseMentionAutocompleteResult.mentionResults.html","deprecated":false},{"id":"namespace_usementionautocompleteresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseMentionAutocompleteResult.mentionSelectedIndex","file":"src/hooks/editor/useMentionAutocomplete.ts","doc":"","url":"./src/hooks/editor/useMentionAutocomplete.ts/~/UseMentionAutocompleteResult.mentionSelectedIndex.html","deprecated":false},{"id":"namespace_usementionautocompleteresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseMentionAutocompleteResult.syncMention","file":"src/hooks/editor/useMentionAutocomplete.ts","doc":"Follows the @query under the caret, searches for it 150 ms after the last keystroke, and closes the list once the caret leaves it. The caller calls it on every change with lookup set, and on every caret move without, since only typing may search.","url":"./src/hooks/editor/useMentionAutocomplete.ts/~/UseMentionAutocompleteResult.syncMention.html","deprecated":false},{"id":"namespace_usementionautocompleteresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseMentionAutocompleteResult.closeMention","file":"src/hooks/editor/useMentionAutocomplete.ts","doc":"","url":"./src/hooks/editor/useMentionAutocomplete.ts/~/UseMentionAutocompleteResult.closeMention.html","deprecated":false},{"id":"namespace_usementionautocompleteresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseMentionAutocompleteResult.handleMentionKeyDown","file":"src/hooks/editor/useMentionAutocomplete.ts","doc":"Handles the arrows, Enter, Tab and Escape while the list is shown, and returns whether it took the key. The caller must then leave the key alone.","url":"./src/hooks/editor/useMentionAutocomplete.ts/~/UseMentionAutocompleteResult.handleMentionKeyDown.html","deprecated":false},{"id":"namespace_usementionautocompleteresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseMentionAutocompleteResult.handleMentionSelect","file":"src/hooks/editor/useMentionAutocomplete.ts","doc":"Inserts @username through replace and closes the list.","url":"./src/hooks/editor/useMentionAutocomplete.ts/~/UseMentionAutocompleteResult.handleMentionSelect.html","deprecated":false},{"id":"namespace_usementionautocomplete","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useMentionAutocomplete","file":"src/hooks/editor/useMentionAutocomplete.ts","doc":"Returns the suggestions' state and the functions that drive them. A pick goes through replace, TextEditor's function that puts the text over [start, end) of the textarea's value, followed by a space when word is set. With everyone, which the chat's composer sets for a role with chat:everyone, @everyone is offered too.","url":"./src/hooks/editor/useMentionAutocomplete.ts/~/useMentionAutocomplete.html","deprecated":false},{"id":"namespace_usedefaultfeedtab","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useDefaultFeedTab","file":"src/hooks/feed/useDefaultFeedTab.ts","doc":"Returns the feed tab the index opens on, and a setter that stores a new choice. The settings page sets it; the feed reads it through useViewerDefaultFeedTab. A new choice reaches every reader at once, in this browser tab and the others.","url":"./src/hooks/feed/useDefaultFeedTab.ts/~/useDefaultFeedTab.html","deprecated":false},{"id":"namespace_useviewerdefaultfeedtab","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useViewerDefaultFeedTab","file":"src/hooks/feed/useDefaultFeedTab.ts","doc":"Returns the tab the bare / and /<category> show this viewer: their choice, or DEFAULT_FEED_TAB for \"follow\" when nobody is signed in, since it needs a session. Index and its tab bar read it.","url":"./src/hooks/feed/useDefaultFeedTab.ts/~/useViewerDefaultFeedTab.html","deprecated":false},{"id":"namespace_fadestate","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"FadeState","file":"src/hooks/feed/useFading.ts","doc":"Held by useFading for each fading item, and mapped to a CSS class by fadeClassName. cooldown lasts 2 seconds, and dismissing lasts the 350ms of the CSS collapse.","url":"./src/hooks/feed/useFading.ts/~/FadeState.html","deprecated":false},{"id":"namespace_usefadingresult","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UseFadingResult","file":"src/hooks/feed/useFading.ts","doc":"Returned by useFading to useUpvotedList and usePlaylist. The list keeps showing an item while it is in fading.","url":"./src/hooks/feed/useFading.ts/~/UseFadingResult.html","deprecated":false},{"id":"namespace_usefadingresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseFadingResult.fading","file":"src/hooks/feed/useFading.ts","doc":"","url":"./src/hooks/feed/useFading.ts/~/UseFadingResult.fading.html","deprecated":false},{"id":"namespace_usefadingresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseFadingResult.startFading","file":"src/hooks/feed/useFading.ts","doc":"Does nothing when id is already fading.","url":"./src/hooks/feed/useFading.ts/~/UseFadingResult.startFading.html","deprecated":false},{"id":"namespace_usefadingresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseFadingResult.cancelFading","file":"src/hooks/feed/useFading.ts","doc":"Called when the removal is undone, so that the item stays.","url":"./src/hooks/feed/useFading.ts/~/UseFadingResult.cancelFading.html","deprecated":false},{"id":"namespace_usefadingresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseFadingResult.cancelAll","file":"src/hooks/feed/useFading.ts","doc":"Called when the list is replaced, as by another user's upvotes.","url":"./src/hooks/feed/useFading.ts/~/UseFadingResult.cancelAll.html","deprecated":false},{"id":"namespace_usefading","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useFading","file":"src/hooks/feed/useFading.ts","doc":"Returns the fading state of a list's items and the calls that drive it. onFaded is called with an item whose fade ran to its end, for the list to drop it; a cancelled fade doesn't call it. The timers are cleared on unmount.","url":"./src/hooks/feed/useFading.ts/~/useFading.html","deprecated":false},{"id":"namespace_fadeclassname","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"fadeClassName","file":"src/hooks/feed/useFading.ts","doc":"Returns the class a fading card takes in phase, for DumpCard's className, or undefined for a card that isn't fading.","url":"./src/hooks/feed/useFading.ts/~/fadeClassName.html","deprecated":false},{"id":"namespace_feedcacheentry","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"FeedCacheEntry","file":"src/hooks/feed/useFeedCache.ts","doc":"Stored as JSON by useFeedCache's saveState, and read back by the hook when the page is next reached by going back.","url":"./src/hooks/feed/useFeedCache.ts/~/FeedCacheEntry.html","deprecated":false},{"id":"namespace_feedcacheentry","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FeedCacheEntry.items","file":"src/hooks/feed/useFeedCache.ts","doc":"It holds every page loaded so far, whose dates JSON turns into strings.","url":"./src/hooks/feed/useFeedCache.ts/~/FeedCacheEntry.items.html","deprecated":false},{"id":"namespace_feedcacheentry","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FeedCacheEntry.page","file":"src/hooks/feed/useFeedCache.ts","doc":"Loading more carries on from this page, the last loaded.","url":"./src/hooks/feed/useFeedCache.ts/~/FeedCacheEntry.page.html","deprecated":false},{"id":"namespace_feedcacheentry","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FeedCacheEntry.hasMore","file":"src/hooks/feed/useFeedCache.ts","doc":"","url":"./src/hooks/feed/useFeedCache.ts/~/FeedCacheEntry.hasMore.html","deprecated":false},{"id":"namespace_feedcacheentry","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FeedCacheEntry.scrollY","file":"src/hooks/feed/useFeedCache.ts","doc":"","url":"./src/hooks/feed/useFeedCache.ts/~/FeedCacheEntry.scrollY.html","deprecated":false},{"id":"namespace_feedcacheentry","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FeedCacheEntry.savedAt","file":"src/hooks/feed/useFeedCache.ts","doc":"In epoch milliseconds.","url":"./src/hooks/feed/useFeedCache.ts/~/FeedCacheEntry.savedAt.html","deprecated":false},{"id":"namespace_savedlist","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"SavedList","file":"src/hooks/feed/useFeedCache.ts","doc":"Passed to useFeedCache's saveState by the feed pages, from the list they hold, without its loading flag.","url":"./src/hooks/feed/useFeedCache.ts/~/SavedList.html","deprecated":false},{"id":"namespace_usefeedcacheresult","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UseFeedCacheResult","file":"src/hooks/feed/useFeedCache.ts","doc":"Returned by useFeedCache to a feed page.","url":"./src/hooks/feed/useFeedCache.ts/~/UseFeedCacheResult.html","deprecated":false},{"id":"namespace_usefeedcacheresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseFeedCacheResult.cached","file":"src/hooks/feed/useFeedCache.ts","doc":"It holds the saved feed when the page was reached by going back or forward and the feed was saved less than 10 minutes ago. It changes only with the key.","url":"./src/hooks/feed/useFeedCache.ts/~/UseFeedCacheResult.cached.html","deprecated":false},{"id":"namespace_usefeedcacheresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseFeedCacheResult.saveState","file":"src/hooks/feed/useFeedCache.ts","doc":"Usually called through useScrollSave, as the page is left.","url":"./src/hooks/feed/useFeedCache.ts/~/UseFeedCacheResult.saveState.html","deprecated":false},{"id":"namespace_usefeedcache","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useFeedCache","file":"src/hooks/feed/useFeedCache.ts","doc":"Returns the feed saved under key and a way to save it. The feed pages and useUserDumpFeed use it. key must tell apart every list whose items differ; the viewer is added to it here, since they see their own private items. hydrateItem restores what JSON lost, such as dates. A full or blocked storage is ignored.","url":"./src/hooks/feed/useFeedCache.ts/~/useFeedCache.html","deprecated":false},{"id":"namespace_useinfinitescroll","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useInfiniteScroll","file":"src/hooks/feed/useInfiniteScroll.ts","doc":"Returns a callback ref for the sentinel element placed after a feed's last item, and calls onLoadMore when the sentinel comes within 200px of the view while enabled. Feed pages pass canLoadMore of their list.The ref is a callback so that the observer follows a new sentinel, as when Index switches tabs and another feed mounts its own.A sentinel still in view after a load asks again, which fills a tall screen, but would also retry a failing request as fast as it fails. So while it stays in view the waits double, from 1s up to 30s, and they start over once it leaves the view or new items push it down.","url":"./src/hooks/feed/useInfiniteScroll.ts/~/useInfiniteScroll.html","deprecated":false},{"id":"namespace_fetchpage","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"FetchPage","file":"src/hooks/feed/usePagedList.ts","doc":"Passed to useLoadMore and usePagedList by a list's page or hook. It resolves to page page of the list, its items deserialized, as fetch with pageUrl and readPage gives it, and rejects when the page can't be had.","url":"./src/hooks/feed/usePagedList.ts/~/FetchPage.html","deprecated":false},{"id":"namespace_useloadmore","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useLoadMore","file":"src/hooks/feed/usePagedList.ts","doc":"Returns the call that loads the page after list's last one and appends it through setList. It does nothing unless canLoadMore(list); a page that fails leaves the list as it was, for the next call to try again. A page that loads its list along with more, as the search page does, uses it directly, and usePagedList for the others.","url":"./src/hooks/feed/usePagedList.ts/~/useLoadMore.html","deprecated":false},{"id":"namespace_usepagedlistresult","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UsePagedListResult","file":"src/hooks/feed/usePagedList.ts","doc":"Returned by usePagedList.","url":"./src/hooks/feed/usePagedList.ts/~/UsePagedListResult.html","deprecated":false},{"id":"namespace_usepagedlistresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UsePagedListResult.state","file":"src/hooks/feed/usePagedList.ts","doc":"","url":"./src/hooks/feed/usePagedList.ts/~/UsePagedListResult.state.html","deprecated":false},{"id":"namespace_usepagedlistresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UsePagedListResult.setItems","file":"src/hooks/feed/usePagedList.ts","doc":"Does nothing until loaded. Passed to the sync hooks.","url":"./src/hooks/feed/usePagedList.ts/~/UsePagedListResult.setItems.html","deprecated":false},{"id":"namespace_usepagedlistresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UsePagedListResult.loadMore","file":"src/hooks/feed/usePagedList.ts","doc":"It goes to useInfiniteScroll or to a LoadMoreButton.","url":"./src/hooks/feed/usePagedList.ts/~/UsePagedListResult.loadMore.html","deprecated":false},{"id":"namespace_usepagedlistresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UsePagedListResult.resync","file":"src/hooks/feed/usePagedList.ts","doc":"Fetches again every page loaded so far and puts them in the list's place, keeping its length and so the scroll. The live lists call it on useOnReconnect, for what changed while the socket was down. A page that fails leaves the list as it was.","url":"./src/hooks/feed/usePagedList.ts/~/UsePagedListResult.resync.html","deprecated":false},{"id":"namespace_usepagedlist","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"usePagedList","file":"src/hooks/feed/usePagedList.ts","doc":"Returns the list fetchPage serves for key, from its first page, and the call that loads the next. key changes as useFetchState's does, and cached, useFeedCache's restored list for it, if any, is shown without loading. The index's feeds, the profile's lists, the notifications and the popover of voters and likers use it.","url":"./src/hooks/feed/usePagedList.ts/~/usePagedList.html","deprecated":false},{"id":"namespace_usepositionmemory","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"usePositionMemory","file":"src/hooks/feed/usePositionMemory.ts","doc":"Remembers the index of every item that leaves items, whatever took it out, for useDumpListSync and usePlaylistListSync, which own the lists' live changes. items is the loaded list, or [] before it loads. The returned call gives an item's old index, once, and forgets it; it is undefined for an item that never left.","url":"./src/hooks/feed/usePositionMemory.ts/~/usePositionMemory.html","deprecated":false},{"id":"namespace_insertat","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"insertAt","file":"src/hooks/feed/usePositionMemory.ts","doc":"Returns list with item at idx, or at the end when the list has since shrunk below it, unless the list holds it already.","url":"./src/hooks/feed/usePositionMemory.ts/~/insertAt.html","deprecated":false},{"id":"namespace_usescrollsave","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useScrollSave","file":"src/hooks/feed/useScrollSave.ts","doc":"Calls onSave(scrollY) when the component unmounts or the tab is hidden (pagehide), while enabled. Feed pages pass enabled once their feed is loaded, and an onSave that calls useFeedCache's saveState.It doesn't save on scroll, since serializing the whole feed there took a long task at every pause.","url":"./src/hooks/feed/useScrollSave.ts/~/useScrollSave.html","deprecated":false},{"id":"namespace_usescrollrestore","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useScrollRestore","file":"src/hooks/feed/useScrollSave.ts","doc":"Scrolls the window to scrollY once loaded, and never again, before paint so that the restored page doesn't flash at the top. Feed pages pass useFeedCache's cached?.scrollY, which is undefined when nothing was restored.","url":"./src/hooks/feed/useScrollSave.ts/~/useScrollRestore.html","deprecated":false},{"id":"namespace_useapiformresult","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UseApiFormResult","file":"src/hooks/form/useApiForm.ts","doc":"Returned by useApiForm, the form with submit added.","url":"./src/hooks/form/useApiForm.ts/~/UseApiFormResult.html","deprecated":false},{"id":"namespace_useapiformresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseApiFormResult.submit","file":"src/hooks/form/useApiForm.ts","doc":"Wraps an async submit handler with the shared API-form lifecycle: clears the previous root error, runs the handler while RHF keeps formState.isSubmitting true, and on a thrown error surfaces a single root error via friendlyFetchError. Pair it with expectOk so API-level failures and network failures both become root errors through one code path. Returns the onSubmit handler to spread onto <form onSubmit={...}>.","url":"./src/hooks/form/useApiForm.ts/~/UseApiFormResult.submit.html","deprecated":false},{"id":"namespace_useapiform","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useApiForm","file":"src/hooks/form/useApiForm.ts","doc":"Returns a react-hook-form form made with options, plus submit, which turns a failed request into the form's root error.","url":"./src/hooks/form/useApiForm.ts/~/useApiForm.html","deprecated":false},{"id":"namespace_usepeaks","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"usePeaks","file":"src/hooks/player/usePeaks.ts","doc":"Returns the peaks of source once loaded, and null until then, without a source, or when it can't be loaded: the scrubber then draws a plain bar.","url":"./src/hooks/player/usePeaks.ts/~/usePeaks.html","deprecated":false},{"id":"namespace_isplayablefile","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isPlayableFile","file":"src/hooks/player/usePlayFile.ts","doc":"Checks whether dump is an uploaded file the global player can play.","url":"./src/hooks/player/usePlayFile.ts/~/isPlayableFile.html","deprecated":false},{"id":"namespace_fileartworkurl","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"fileArtworkUrl","file":"src/hooks/player/usePlayFile.ts","doc":"Returns the artwork of an uploaded file, for its thumbnail and the player: the uploaded thumbnail, or the server's still of a video or scaled-down copy of an image. A bare audio file has none, since the thumbnail endpoint has nothing to serve for it, and shows a placeholder instead.","url":"./src/hooks/player/usePlayFile.ts/~/fileArtworkUrl.html","deprecated":false},{"id":"namespace_useplayfileresult","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UsePlayFileResult","file":"src/hooks/player/usePlayFile.ts","doc":"Returned by usePlayFile to the views that play an uploaded file.","url":"./src/hooks/player/usePlayFile.ts/~/UsePlayFileResult.html","deprecated":false},{"id":"namespace_useplayfileresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UsePlayFileResult.fileUrl","file":"src/hooks/player/usePlayFile.ts","doc":"The file's URL, with the viewer's media token, as the player loads it.","url":"./src/hooks/player/usePlayFile.ts/~/UsePlayFileResult.fileUrl.html","deprecated":false},{"id":"namespace_useplayfileresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UsePlayFileResult.active","file":"src/hooks/player/usePlayFile.ts","doc":"True while the file is the player's current item, playing or paused.","url":"./src/hooks/player/usePlayFile.ts/~/UsePlayFileResult.active.html","deprecated":false},{"id":"namespace_useplayfileresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UsePlayFileResult.playing","file":"src/hooks/player/usePlayFile.ts","doc":"True while the file is playing.","url":"./src/hooks/player/usePlayFile.ts/~/UsePlayFileResult.playing.html","deprecated":false},{"id":"namespace_useplayfileresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UsePlayFileResult.toggle","file":"src/hooks/player/usePlayFile.ts","doc":"Plays the file from the start, or pauses and resumes it once it is the player's current item, so a second click doesn't restart it.","url":"./src/hooks/player/usePlayFile.ts/~/UsePlayFileResult.toggle.html","deprecated":false},{"id":"namespace_useplayfile","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"usePlayFile","file":"src/hooks/player/usePlayFile.ts","doc":"Returns the playback state of the uploaded file dump and a function that plays or pauses it. The player's title links to the dump's page.","url":"./src/hooks/player/usePlayFile.ts/~/usePlayFile.html","deprecated":false},{"id":"namespace_playablerichcontent","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PlayableRichContent","file":"src/hooks/player/usePlayRichContent.ts","doc":"Passed to playRichContent and canPlayRichContent by RichContentCard and JournalCard. It is a dump's RichContent, its thumbnail replaced by the dump's own when it has one.","url":"./src/hooks/player/usePlayRichContent.ts/~/PlayableRichContent.html","deprecated":false},{"id":"namespace_playablerichcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlayableRichContent.type","file":"src/hooks/player/usePlayRichContent.ts","doc":"The provider, as in RichContent.type.","url":"./src/hooks/player/usePlayRichContent.ts/~/PlayableRichContent.type.html","deprecated":false},{"id":"namespace_playablerichcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlayableRichContent.url","file":"src/hooks/player/usePlayRichContent.ts","doc":"The page, which native Bandcamp playback resolves.","url":"./src/hooks/player/usePlayRichContent.ts/~/PlayableRichContent.url.html","deprecated":false},{"id":"namespace_playablerichcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlayableRichContent.title","file":"src/hooks/player/usePlayRichContent.ts","doc":"","url":"./src/hooks/player/usePlayRichContent.ts/~/PlayableRichContent.title.html","deprecated":false},{"id":"namespace_playablerichcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlayableRichContent.embedUrl","file":"src/hooks/player/usePlayRichContent.ts","doc":"","url":"./src/hooks/player/usePlayRichContent.ts/~/PlayableRichContent.embedUrl.html","deprecated":false},{"id":"namespace_playablerichcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlayableRichContent.thumbnailUrl","file":"src/hooks/player/usePlayRichContent.ts","doc":"Shown in the player's header, unless Bandcamp has album art of its own.","url":"./src/hooks/player/usePlayRichContent.ts/~/PlayableRichContent.thumbnailUrl.html","deprecated":false},{"id":"namespace_playablerichcontent","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlayableRichContent.siteName","file":"src/hooks/player/usePlayRichContent.ts","doc":"Shown under the title in the player's header.","url":"./src/hooks/player/usePlayRichContent.ts/~/PlayableRichContent.siteName.html","deprecated":false},{"id":"namespace_useplayrichcontentresult","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UsePlayRichContentResult","file":"src/hooks/player/usePlayRichContent.ts","doc":"Returned by usePlayRichContent to the cards that play a link.","url":"./src/hooks/player/usePlayRichContent.ts/~/UsePlayRichContentResult.html","deprecated":false},{"id":"namespace_useplayrichcontentresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UsePlayRichContentResult.playRichContent","file":"src/hooks/player/usePlayRichContent.ts","doc":"Plays rc, its title in the player linking to the dump page dumpHref. Resolves to false when nothing could play, so the caller can open the link instead.","url":"./src/hooks/player/usePlayRichContent.ts/~/UsePlayRichContentResult.playRichContent.html","deprecated":false},{"id":"namespace_useplayrichcontentresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UsePlayRichContentResult.pending","file":"src/hooks/player/usePlayRichContent.ts","doc":"True while a Bandcamp page is being resolved.","url":"./src/hooks/player/usePlayRichContent.ts/~/UsePlayRichContentResult.pending.html","deprecated":false},{"id":"namespace_useplayrichcontent","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"usePlayRichContent","file":"src/hooks/player/usePlayRichContent.ts","doc":"Returns a function that plays a link's preview in its provider's embed. When the deployment sets GERBEUR_BANDCAMP_PLAYER=native, a Bandcamp page is resolved into its mp3 streams instead and played as a queue, which autoplays and plays an album through. If that fails (offline, a preorder, Bandcamp changing its markup), the embed plays, and a page without one (an artist's root, a /music index) plays nothing.","url":"./src/hooks/player/usePlayRichContent.ts/~/usePlayRichContent.html","deprecated":false},{"id":"namespace_canplayrichcontent","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"canPlayRichContent","file":"src/hooks/player/usePlayRichContent.ts","doc":"Checks whether rc can be played, for the cards to offer a play button. In native mode a Bandcamp page plays even without an embed, since its streams are resolved from the page itself.","url":"./src/hooks/player/usePlayRichContent.ts/~/canPlayRichContent.html","deprecated":false},{"id":"namespace_playlistrow","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PlaylistRow","file":"src/hooks/player/useYouTubePlaylist.ts","doc":"A row of the tracklist GlobalPlayer shows. Its title and length come from the server's list, and are missing for a video that list lacks.","url":"./src/hooks/player/useYouTubePlaylist.ts/~/PlaylistRow.html","deprecated":false},{"id":"namespace_playlistrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistRow.videoId","file":"src/hooks/player/useYouTubePlaylist.ts","doc":"","url":"./src/hooks/player/useYouTubePlaylist.ts/~/PlaylistRow.videoId.html","deprecated":false},{"id":"namespace_playlistrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistRow.title","file":"src/hooks/player/useYouTubePlaylist.ts","doc":"","url":"./src/hooks/player/useYouTubePlaylist.ts/~/PlaylistRow.title.html","deprecated":false},{"id":"namespace_playlistrow","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistRow.duration","file":"src/hooks/player/useYouTubePlaylist.ts","doc":"In seconds.","url":"./src/hooks/player/useYouTubePlaylist.ts/~/PlaylistRow.duration.html","deprecated":false},{"id":"namespace_useyoutubeplaylistresult","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UseYouTubePlaylistResult","file":"src/hooks/player/useYouTubePlaylist.ts","doc":"Returned by useYouTubePlaylist to GlobalPlayer, which shows the tracklist and its transport when there is more than one row.","url":"./src/hooks/player/useYouTubePlaylist.ts/~/UseYouTubePlaylistResult.html","deprecated":false},{"id":"namespace_useyoutubeplaylistresult","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"UseYouTubePlaylistResult.playAt","file":"src/hooks/player/useYouTubePlaylist.ts","doc":"","url":"./src/hooks/player/useYouTubePlaylist.ts/~/UseYouTubePlaylistResult.playAt.html","deprecated":false},{"id":"namespace_useyoutubeplaylistresult","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"UseYouTubePlaylistResult.next","file":"src/hooks/player/useYouTubePlaylist.ts","doc":"","url":"./src/hooks/player/useYouTubePlaylist.ts/~/UseYouTubePlaylistResult.next.html","deprecated":false},{"id":"namespace_useyoutubeplaylistresult","kind":[{"char":"m","kind":"Method","title":"Method"}],"name":"UseYouTubePlaylistResult.previous","file":"src/hooks/player/useYouTubePlaylist.ts","doc":"","url":"./src/hooks/player/useYouTubePlaylist.ts/~/UseYouTubePlaylistResult.previous.html","deprecated":false},{"id":"namespace_useyoutubeplaylistresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseYouTubePlaylistResult.rows","file":"src/hooks/player/useYouTubePlaylist.ts","doc":"","url":"./src/hooks/player/useYouTubePlaylist.ts/~/UseYouTubePlaylistResult.rows.html","deprecated":false},{"id":"namespace_useyoutubeplaylistresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseYouTubePlaylistResult.index","file":"src/hooks/player/useYouTubePlaylist.ts","doc":"The playing row, or -1 while the player hasn't reported one.","url":"./src/hooks/player/useYouTubePlaylist.ts/~/UseYouTubePlaylistResult.index.html","deprecated":false},{"id":"namespace_useyoutubeplaylistresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseYouTubePlaylistResult.ready","file":"src/hooks/player/useYouTubePlaylist.ts","doc":"Whether the IFrame API drives the embed. Rows are clickable only then.","url":"./src/hooks/player/useYouTubePlaylist.ts/~/UseYouTubePlaylistResult.ready.html","deprecated":false},{"id":"namespace_useyoutubeplaylist","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useYouTubePlaylist","file":"src/hooks/player/useYouTubePlaylist.ts","doc":"Returns the tracklist and transport of the playlist embedUrl plays in the iframe iframeRef, or no rows when it plays none. The iframe's URL must carry enablejsapi (see withJsApi) for the API to drive it.","url":"./src/hooks/player/useYouTubePlaylist.ts/~/useYouTubePlaylist.html","deprecated":false},{"id":"namespace_useplaylistresult","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UsePlaylistResult","file":"src/hooks/playlist/usePlaylist.ts","doc":"Returned by usePlaylist to PlaylistDetail.","url":"./src/hooks/playlist/usePlaylist.ts/~/UsePlaylistResult.html","deprecated":false},{"id":"namespace_useplaylistresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UsePlaylistResult.state","file":"src/hooks/playlist/usePlaylist.ts","doc":"","url":"./src/hooks/playlist/usePlaylist.ts/~/UsePlaylistResult.state.html","deprecated":false},{"id":"namespace_useplaylistresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UsePlaylistResult.fading","file":"src/hooks/playlist/usePlaylist.ts","doc":"It holds the dumps being removed, which stay listed while they fade. A dump in it can't be dragged, and during its cooldown its removal can be undone.","url":"./src/hooks/playlist/usePlaylist.ts/~/UsePlaylistResult.fading.html","deprecated":false},{"id":"namespace_useplaylistresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UsePlaylistResult.actionError","file":"src/hooks/playlist/usePlaylist.ts","doc":"It says why the server refused a removal, a reorder or a delete.","url":"./src/hooks/playlist/usePlaylist.ts/~/UsePlaylistResult.actionError.html","deprecated":false},{"id":"namespace_useplaylistresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UsePlaylistResult.applyDetails","file":"src/hooks/playlist/usePlaylist.ts","doc":"Shows the playlist as PlaylistEditForm saved it.","url":"./src/hooks/playlist/usePlaylist.ts/~/UsePlaylistResult.applyDetails.html","deprecated":false},{"id":"namespace_useplaylistresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UsePlaylistResult.remove","file":"src/hooks/playlist/usePlaylist.ts","doc":"Fades the dump out, and takes it out of the playlist on the server when the fade ends, or when the page is left before.","url":"./src/hooks/playlist/usePlaylist.ts/~/UsePlaylistResult.remove.html","deprecated":false},{"id":"namespace_useplaylistresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UsePlaylistResult.undoRemove","file":"src/hooks/playlist/usePlaylist.ts","doc":"Keeps a dump that remove is fading out. Nothing was sent yet.","url":"./src/hooks/playlist/usePlaylist.ts/~/UsePlaylistResult.undoRemove.html","deprecated":false},{"id":"namespace_useplaylistresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UsePlaylistResult.move","file":"src/hooks/playlist/usePlaylist.ts","doc":"Moves the dump at from to to, counted among the dumps not fading, on screen only, as a drag goes along.","url":"./src/hooks/playlist/usePlaylist.ts/~/UsePlaylistResult.move.html","deprecated":false},{"id":"namespace_useplaylistresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UsePlaylistResult.saveOrder","file":"src/hooks/playlist/usePlaylist.ts","doc":"Sends the order move left, as a drag ends.","url":"./src/hooks/playlist/usePlaylist.ts/~/UsePlaylistResult.saveOrder.html","deprecated":false},{"id":"namespace_useplaylistresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UsePlaylistResult.deletePlaylist","file":"src/hooks/playlist/usePlaylist.ts","doc":"Leaves for home once the playlist is deleted, or sets actionError.","url":"./src/hooks/playlist/usePlaylist.ts/~/UsePlaylistResult.deletePlaylist.html","deprecated":false},{"id":"namespace_useplaylist","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"usePlaylist","file":"src/hooks/playlist/usePlaylist.ts","doc":"Returns the playlist at /@username/playlists/slug from GET /api/users/@:username/playlists/:slug, with the dumps the viewer may see in it. The socket's events keep its details and dumps live: a dump another client removes, or that turns private, fades out, one it adds, or that turns public, is fetched, a new order is applied, and a playlist deleted, or turned private by someone else, sends the page home. A reconnection loads it again. A new slug replaces the URL, keeping the page's view, and a path that names the playlist on screen, as that one does, fetches nothing.","url":"./src/hooks/playlist/usePlaylist.ts/~/usePlaylist.html","deprecated":false},{"id":"namespace_playlistlistsyncoptions","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PlaylistListSyncOptions","file":"src/hooks/playlist/usePlaylistListSync.ts","doc":"Passed to usePlaylistListSync by each page, to fit its list.","url":"./src/hooks/playlist/usePlaylistListSync.ts/~/PlaylistListSyncOptions.html","deprecated":false},{"id":"namespace_playlistlistsyncoptions","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistListSyncOptions.isOwner","file":"src/hooks/playlist/usePlaylistListSync.ts","doc":"Keeps private playlists in the list, for their owner.","url":"./src/hooks/playlist/usePlaylistListSync.ts/~/PlaylistListSyncOptions.isOwner.html","deprecated":false},{"id":"namespace_playlistlistsyncoptions","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistListSyncOptions.ownerId","file":"src/hooks/playlist/usePlaylistListSync.ts","doc":"Adds only this user's playlists, when one is created or comes back into view. Without it, anyone's are added.","url":"./src/hooks/playlist/usePlaylistListSync.ts/~/PlaylistListSyncOptions.ownerId.html","deprecated":false},{"id":"namespace_playlistlistsyncoptions","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistListSyncOptions.sort","file":"src/hooks/playlist/usePlaylistListSync.ts","doc":"The order the list is in, for one the API sorts: the playlists page's and a profile's. A list in an order of its own leaves it out, the followed playlists being by the date they were followed and a search's results the search's: it takes no new playlist, since the socket says neither what the user follows nor what a search matches, and moves none. Playlists already listed still change, go, and come back where they were.","url":"./src/hooks/playlist/usePlaylistListSync.ts/~/PlaylistListSyncOptions.sort.html","deprecated":false},{"id":"namespace_useplaylistlistsync","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"usePlaylistListSync","file":"src/hooks/playlist/usePlaylistListSync.ts","doc":"Applies the socket's playlist events to items, the loaded list, which setPlaylists updates. A created playlist goes where the list's order puts it, an updated one changes in place or leaves when it turns private (unless isOwner), one that left comes back where it was when it returns, a deleted one leaves, and a playlist's dumpCount and lastDumpAt follow its dumps. One that a change brings up the order moves up to its place, as a playlist does in the updated order when it takes a dump; one that falls stays where it is, its place being perhaps on a page not loaded. A renamed user's playlists take their new name.","url":"./src/hooks/playlist/usePlaylistListSync.ts/~/usePlaylistListSync.html","deprecated":false},{"id":"namespace_useplaylistmembershipsresult","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UsePlaylistMembershipsResult","file":"src/hooks/playlist/usePlaylistMemberships.ts","doc":"Returned by usePlaylistMemberships to AddToPlaylistModal and DumpCreateModal, for their PlaylistMembershipPanel.","url":"./src/hooks/playlist/usePlaylistMemberships.ts/~/UsePlaylistMembershipsResult.html","deprecated":false},{"id":"namespace_useplaylistmembershipsresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UsePlaylistMembershipsResult.memberships","file":"src/hooks/playlist/usePlaylistMemberships.ts","doc":"Empty while loading, and when the load failed.","url":"./src/hooks/playlist/usePlaylistMemberships.ts/~/UsePlaylistMembershipsResult.memberships.html","deprecated":false},{"id":"namespace_useplaylistmembershipsresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UsePlaylistMembershipsResult.loading","file":"src/hooks/playlist/usePlaylistMemberships.ts","doc":"","url":"./src/hooks/playlist/usePlaylistMemberships.ts/~/UsePlaylistMembershipsResult.loading.html","deprecated":false},{"id":"namespace_useplaylistmembershipsresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UsePlaylistMembershipsResult.toggle","file":"src/hooks/playlist/usePlaylistMemberships.ts","doc":"Adds the dump to the playlist or takes it out on the server, and shows it only once the server agrees. A refusal or a dropped connection changes nothing.","url":"./src/hooks/playlist/usePlaylistMemberships.ts/~/UsePlaylistMembershipsResult.toggle.html","deprecated":false},{"id":"namespace_useplaylistmembershipsresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UsePlaylistMembershipsResult.add","file":"src/hooks/playlist/usePlaylistMemberships.ts","doc":"Puts first a playlist the panel just created with the dump in it.","url":"./src/hooks/playlist/usePlaylistMemberships.ts/~/UsePlaylistMembershipsResult.add.html","deprecated":false},{"id":"namespace_useplaylistmemberships","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"usePlaylistMemberships","file":"src/hooks/playlist/usePlaylistMemberships.ts","doc":"Returns the user's playlists with whether each holds dumpId, from GET /api/me/playlists?contains=:dumpId. A null dumpId, as before DumpCreateModal has posted its dump, loads nothing.","url":"./src/hooks/playlist/usePlaylistMemberships.ts/~/usePlaylistMemberships.html","deprecated":false},{"id":"namespace_useprofileresult","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UseProfileResult","file":"src/hooks/profile/useProfile.ts","doc":"Returned by useProfile to UserPublicProfile.","url":"./src/hooks/profile/useProfile.ts/~/UseProfileResult.html","deprecated":false},{"id":"namespace_useprofileresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseProfileResult.state","file":"src/hooks/profile/useProfile.ts","doc":"","url":"./src/hooks/profile/useProfile.ts/~/UseProfileResult.state.html","deprecated":false},{"id":"namespace_useprofileresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseProfileResult.isOwnProfile","file":"src/hooks/profile/useProfile.ts","doc":"It is false while the profile loads.","url":"./src/hooks/profile/useProfile.ts/~/UseProfileResult.isOwnProfile.html","deprecated":false},{"id":"namespace_useprofileresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseProfileResult.setUser","file":"src/hooks/profile/useProfile.ts","doc":"It shows the header's edits, which the server echoes to other browsers.","url":"./src/hooks/profile/useProfile.ts/~/UseProfileResult.setUser.html","deprecated":false},{"id":"namespace_useprofile","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useProfile","file":"src/hooks/profile/useProfile.ts","doc":"Returns the user named username, from GET /api/users/@:username, which answers a former name or another case too. The profile then puts the current name in its URL, and that path, naming the user on screen, fetches nothing; another user's does. The socket's user_updated keeps them live, and a reconnection fetches them again.","url":"./src/hooks/profile/useProfile.ts/~/useProfile.html","deprecated":false},{"id":"namespace_anchoredfloatoptions","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"AnchoredFloatOptions","file":"src/hooks/shared/useAnchoredFloat.ts","doc":"Passed to useAnchoredFloat by the component that owns the panel, in pixels. The heights let the hook size the panel's scrolling part to the room left.","url":"./src/hooks/shared/useAnchoredFloat.ts/~/AnchoredFloatOptions.html","deprecated":false},{"id":"namespace_anchoredfloatoptions","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AnchoredFloatOptions.width","file":"src/hooks/shared/useAnchoredFloat.ts","doc":"A width, or \"anchor\" for the anchor's own. Either shrinks to fit a narrower viewport.","url":"./src/hooks/shared/useAnchoredFloat.ts/~/AnchoredFloatOptions.width.html","deprecated":false},{"id":"namespace_anchoredfloatoptions","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AnchoredFloatOptions.chromeHeight","file":"src/hooks/shared/useAnchoredFloat.ts","doc":"The height of the panel's parts that don't scroll, borders included.","url":"./src/hooks/shared/useAnchoredFloat.ts/~/AnchoredFloatOptions.chromeHeight.html","deprecated":false},{"id":"namespace_anchoredfloatoptions","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AnchoredFloatOptions.minContentHeight","file":"src/hooks/shared/useAnchoredFloat.ts","doc":"","url":"./src/hooks/shared/useAnchoredFloat.ts/~/AnchoredFloatOptions.minContentHeight.html","deprecated":false},{"id":"namespace_anchoredfloatoptions","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"AnchoredFloatOptions.maxContentHeight","file":"src/hooks/shared/useAnchoredFloat.ts","doc":"","url":"./src/hooks/shared/useAnchoredFloat.ts/~/AnchoredFloatOptions.maxContentHeight.html","deprecated":false},{"id":"namespace_useanchoredfloat","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useAnchoredFloat","file":"src/hooks/shared/useAnchoredFloat.ts","doc":"Returns the style that places a panel above or below anchorRef, whichever has more room, kept inside the viewport and following scrolls and resizes. The panel must be portaled out of any clipping ancestor, and its scrolling part must take its height from the --float-max-h property of the style.It returns null while open is false, and also on the first render after opening, until the panel is measured. The caller hides the panel meanwhile.","url":"./src/hooks/shared/useAnchoredFloat.ts/~/useAnchoredFloat.html","deprecated":false},{"id":"namespace_usecanonicalpath","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useCanonicalPath","file":"src/hooks/shared/useCanonicalPath.ts","doc":"Replaces the current path with canonical when they differ, keeping the query string, the hash and the history entry's state. It replaces the entry, so going back skips the old path. Nothing happens while canonical is null, as while the page loads. The profile, dump, dump editor and playlist pages call it.","url":"./src/hooks/shared/useCanonicalPath.ts/~/useCanonicalPath.html","deprecated":false},{"id":"namespace_usecardlinkresult","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UseCardLinkResult","file":"src/hooks/shared/useCardLink.ts","doc":"Returned by useCardLink to PlaylistCard, and through useDumpCardLink to DumpCard and JournalCard.","url":"./src/hooks/shared/useCardLink.ts/~/UseCardLinkResult.html","deprecated":false},{"id":"namespace_usecardlinkresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseCardLinkResult.go","file":"src/hooks/shared/useCardLink.ts","doc":"Opens the page in this tab, for a handler that would rather not play.","url":"./src/hooks/shared/useCardLink.ts/~/UseCardLinkResult.go.html","deprecated":false},{"id":"namespace_usecardlinkresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseCardLinkResult.handledAsNewTab","file":"src/hooks/shared/useCardLink.ts","doc":"Opens the page in a new tab and returns true when e is a ctrl, cmd or shift click away from any anchor. A click handler that plays media calls it first, so that such a click opens the page instead.","url":"./src/hooks/shared/useCardLink.ts/~/UseCardLinkResult.handledAsNewTab.html","deprecated":false},{"id":"namespace_usecardlinkresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseCardLinkResult.cardProps","file":"src/hooks/shared/useCardLink.ts","doc":"Spread onto the card element.","url":"./src/hooks/shared/useCardLink.ts/~/UseCardLinkResult.cardProps.html","deprecated":false},{"id":"namespace_usecardlinkresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseCardLinkResult.cardProps.onClick","file":"src/hooks/shared/useCardLink.ts","doc":"","url":"./src/hooks/shared/useCardLink.ts/~/UseCardLinkResult.cardProps.onClick.html","deprecated":false},{"id":"namespace_usecardlinkresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseCardLinkResult.cardProps.onMouseDown","file":"src/hooks/shared/useCardLink.ts","doc":"","url":"./src/hooks/shared/useCardLink.ts/~/UseCardLinkResult.cardProps.onMouseDown.html","deprecated":false},{"id":"namespace_usecardlinkresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseCardLinkResult.cardProps.onAuxClick","file":"src/hooks/shared/useCardLink.ts","doc":"","url":"./src/hooks/shared/useCardLink.ts/~/UseCardLinkResult.cardProps.onAuxClick.html","deprecated":false},{"id":"namespace_usecardlink","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useCardLink","file":"src/hooks/shared/useCardLink.ts","doc":"Returns the handlers that make a card open the page at url: in this tab on a click, in a new tab on a middle click or a ctrl, cmd or shift click. Every way it opens the page calls onOpen first, which marks the item visited. Anchors inside the card, such as the title or a category, keep their own target.","url":"./src/hooks/shared/useCardLink.ts/~/useCardLink.html","deprecated":false},{"id":"namespace_site_name","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"SITE_NAME","file":"src/hooks/shared/useDocumentTitle.ts","doc":"The site's name, read once at startup, as the header shows it.","url":"./src/hooks/shared/useDocumentTitle.ts/~/SITE_NAME.html","deprecated":false},{"id":"namespace_site_emoji","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"SITE_EMOJI","file":"src/hooks/shared/useDocumentTitle.ts","doc":"The site's emoji, read once at startup, as the header shows it.","url":"./src/hooks/shared/useDocumentTitle.ts/~/SITE_EMOJI.html","deprecated":false},{"id":"namespace_usedocumenttitle","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useDocumentTitle","file":"src/hooks/shared/useDocumentTitle.ts","doc":"Sets the tab's title to title · site name for the page that calls it, since a client-side navigation leaves the server's <title> in place. A page passes null for the bare site name, and undefined while its data loads, which keeps the title the server rendered for that URL rather than flashing the site name.","url":"./src/hooks/shared/useDocumentTitle.ts/~/useDocumentTitle.html","deprecated":false},{"id":"namespace_settitlebadge","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"setTitleBadge","file":"src/hooks/shared/useDocumentTitle.ts","doc":"Prefixes the tab's title with the unread count, as in \"(3) Chat · gerbeur\", or removes the prefix at 0. Past 99 it shows \"99+\".","url":"./src/hooks/shared/useDocumentTitle.ts/~/setTitleBadge.html","deprecated":false},{"id":"namespace_fetchstate","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"FetchState","file":"src/hooks/shared/useFetchState.ts","doc":"Held by useFetchState, and passed on to ListState.","url":"./src/hooks/shared/useFetchState.ts/~/FetchState.html","deprecated":false},{"id":"namespace_fetchstateoptions","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"FetchStateOptions","file":"src/hooks/shared/useFetchState.ts","doc":"Passed to useFetchState.","url":"./src/hooks/shared/useFetchState.ts/~/FetchStateOptions.html","deprecated":false},{"id":"namespace_fetchstateoptions","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FetchStateOptions.enabled","file":"src/hooks/shared/useFetchState.ts","doc":"False until it should load, as the profile's tabs pass \"this tab is open\". Turning it off doesn't abort a load under way, so those tabs finish loading in the background. True by default.","url":"./src/hooks/shared/useFetchState.ts/~/FetchStateOptions.enabled.html","deprecated":false},{"id":"namespace_fetchstateoptions","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"FetchStateOptions.initial","file":"src/hooks/shared/useFetchState.ts","doc":"It holds the data already at hand for a new key, as a feed restored from useFeedCache, which starts loaded and isn't loaded again. It is read only when the key changes.","url":"./src/hooks/shared/useFetchState.ts/~/FetchStateOptions.initial.html","deprecated":false},{"id":"namespace_usefetchstateresult","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UseFetchStateResult","file":"src/hooks/shared/useFetchState.ts","doc":"Returned by useFetchState.","url":"./src/hooks/shared/useFetchState.ts/~/UseFetchStateResult.html","deprecated":false},{"id":"namespace_usefetchstateresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseFetchStateResult.state","file":"src/hooks/shared/useFetchState.ts","doc":"","url":"./src/hooks/shared/useFetchState.ts/~/UseFetchStateResult.state.html","deprecated":false},{"id":"namespace_usefetchstateresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseFetchStateResult.setData","file":"src/hooks/shared/useFetchState.ts","doc":"Edits the loaded data, as when a next page comes in. It does nothing until loaded.","url":"./src/hooks/shared/useFetchState.ts/~/UseFetchStateResult.setData.html","deprecated":false},{"id":"namespace_usefetchstateresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseFetchStateResult.reload","file":"src/hooks/shared/useFetchState.ts","doc":"Loads the key's data again, and replaces the data loaded with it, as the live pages do on useOnReconnect. Until it arrives, the data shown stays, and so it does if the load fails. It does nothing until loaded.","url":"./src/hooks/shared/useFetchState.ts/~/UseFetchStateResult.reload.html","deprecated":false},{"id":"namespace_usefetchstate","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useFetchState","file":"src/hooks/shared/useFetchState.ts","doc":"Returns what load resolves to for key, loaded the first time it is enabled, and kept afterwards. A new key starts over and aborts the load of the last one, as leaving the page does; an undefined key loads nothing. The key must change with whatever the load depends on, the viewer included when it is signed in. load must reject with an Error, as expectOk does, whose message it shows.","url":"./src/hooks/shared/useFetchState.ts/~/useFetchState.html","deprecated":false},{"id":"namespace_useheighttransition","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useHeightTransition","file":"src/hooks/shared/useHeightTransition.ts","doc":"Returns a callback ref for the element whose height eases whenever watch changes, usually the flag that swaps its content. Only the box is animated, so the content that appears should take the animate-in class to fade in. The duration follows --dur-reveal, and nothing moves under prefers-reduced-motion.","url":"./src/hooks/shared/useHeightTransition.ts/~/useHeightTransition.html","deprecated":false},{"id":"namespace_roombesideoptions","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"RoomBesideOptions","file":"src/hooks/shared/useRoomBeside.ts","doc":"Passed to useRoomBeside by PresenceRow, from its own props. Without both selectors, the hook measures nothing and returns null.","url":"./src/hooks/shared/useRoomBeside.ts/~/RoomBesideOptions.html","deprecated":false},{"id":"namespace_roombesideoptions","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RoomBesideOptions.within","file":"src/hooks/shared/useRoomBeside.ts","doc":"Selects the ancestor that bounds the row.","url":"./src/hooks/shared/useRoomBeside.ts/~/RoomBesideOptions.within.html","deprecated":false},{"id":"namespace_roombesideoptions","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RoomBesideOptions.beside","file":"src/hooks/shared/useRoomBeside.ts","doc":"Selects, inside that ancestor, the element that takes its room first.","url":"./src/hooks/shared/useRoomBeside.ts/~/RoomBesideOptions.beside.html","deprecated":false},{"id":"namespace_useroombeside","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useRoomBeside","file":"src/hooks/shared/useRoomBeside.ts","doc":"Returns the width el has to itself in a row it shares with an element that comes first, such as the tabs that leave room for the presence avatars. The first element counts at its content's natural width, since that depends on the theme's fonts and the locale, and the row's gap is taken off too. It returns null until measured.It takes the element itself, from a callback ref, so that the measuring starts whenever it mounts. The element's own width doesn't enter into it, so it can size itself to the answer without feedback.","url":"./src/hooks/shared/useRoomBeside.ts/~/useRoomBeside.html","deprecated":false},{"id":"namespace_usescrolllock","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useScrollLock","file":"src/hooks/shared/useScrollLock.ts","doc":"Freezes the page's scroll while the calling component is mounted, so that the page doesn't slide under a dialog's backdrop. Nested locks are counted.","url":"./src/hooks/shared/useScrollLock.ts/~/useScrollLock.html","deprecated":false},{"id":"namespace_usesoundsenabled","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useSoundsEnabled","file":"src/hooks/shared/useSoundsEnabled.ts","doc":"Returns whether sounds are on in this browser, and a setter that stores the choice. playChime reads the stored value each time it plays, so the choice applies at once without this hook, and another mounted copy of it isn't updated.","url":"./src/hooks/shared/useSoundsEnabled.ts/~/useSoundsEnabled.html","deprecated":false},{"id":"namespace_usetabparam","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useTabParam","file":"src/hooks/shared/useTabParam.ts","doc":"Returns the tab the path segment after base names, defaultTab on the bare base, or null when the segment names none of validTabs, for the page to answer as not found; and a setter that navigates to a tab in place of the current history entry, the default tab to the bare base, with the query string search, the current one by default. A segment after the tab's, as the profile's /follow/playlists, is the tab's own business.","url":"./src/hooks/shared/useTabParam.ts/~/useTabParam.html","deprecated":false},{"id":"namespace_usecommunityfeed","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useCommunityFeed","file":"src/hooks/social/useCommunityFeed.ts","doc":"Returns the community feed, kept up to date for as long as the component is mounted, or null until it is loaded and for a visitor. The CommunityFeed component renders it. Needs CommunityFeedProvider above, which App mounts around every page.","url":"./src/hooks/social/useCommunityFeed.ts/~/useCommunityFeed.html","deprecated":false},{"id":"namespace_usefollows","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useFollows","file":"src/hooks/social/useFollows.ts","doc":"Returns the users and playlists the signed-in user follows, and the functions that follow and unfollow them. Needs FollowProvider above, which App mounts around every page.","url":"./src/hooks/social/useFollows.ts/~/useFollows.html","deprecated":false},{"id":"namespace_usetheme","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useTheme","file":"src/hooks/theme/useTheme.ts","doc":"Returns the style and color scheme, and their setters. The profile page's settings are the only place that changes them.","url":"./src/hooks/theme/useTheme.ts/~/useTheme.html","deprecated":false},{"id":"namespace_themechoicespec","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ThemeChoiceSpec","file":"src/hooks/theme/useThemeChoice.ts","doc":"Passed to useThemeChoice by ThemeProvider, as a constant: one for the style, one for the scheme.","url":"./src/hooks/theme/useThemeChoice.ts/~/ThemeChoiceSpec.html","deprecated":false},{"id":"namespace_themechoicespec","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ThemeChoiceSpec.storageKey","file":"src/hooks/theme/useThemeChoice.ts","doc":"The localStorage key, which index.html's script reads too.","url":"./src/hooks/theme/useThemeChoice.ts/~/ThemeChoiceSpec.storageKey.html","deprecated":false},{"id":"namespace_themechoicespec","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ThemeChoiceSpec.allowed","file":"src/hooks/theme/useThemeChoice.ts","doc":"","url":"./src/hooks/theme/useThemeChoice.ts/~/ThemeChoiceSpec.allowed.html","deprecated":false},{"id":"namespace_themechoicespec","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ThemeChoiceSpec.setting","file":"src/hooks/theme/useThemeChoice.ts","doc":"The account setting that holds the choice.","url":"./src/hooks/theme/useThemeChoice.ts/~/ThemeChoiceSpec.setting.html","deprecated":false},{"id":"namespace_themechoicespec","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ThemeChoiceSpec.fallback","file":"src/hooks/theme/useThemeChoice.ts","doc":"What applies when nobody chose.","url":"./src/hooks/theme/useThemeChoice.ts/~/ThemeChoiceSpec.fallback.html","deprecated":false},{"id":"namespace_themechoicespec","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ThemeChoiceSpec.attribute","file":"src/hooks/theme/useThemeChoice.ts","doc":"The root element's attribute the stylesheets key on.","url":"./src/hooks/theme/useThemeChoice.ts/~/ThemeChoiceSpec.attribute.html","deprecated":false},{"id":"namespace_themechoicespec","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ThemeChoiceSpec.base","file":"src/hooks/theme/useThemeChoice.ts","doc":"The value the stylesheets draw without the attribute, which is then left out.","url":"./src/hooks/theme/useThemeChoice.ts/~/ThemeChoiceSpec.base.html","deprecated":false},{"id":"namespace_usethemechoiceresult","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"UseThemeChoiceResult","file":"src/hooks/theme/useThemeChoice.ts","doc":"Returned by useThemeChoice to ThemeProvider.","url":"./src/hooks/theme/useThemeChoice.ts/~/UseThemeChoiceResult.html","deprecated":false},{"id":"namespace_usethemechoiceresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseThemeChoiceResult.value","file":"src/hooks/theme/useThemeChoice.ts","doc":"","url":"./src/hooks/theme/useThemeChoice.ts/~/UseThemeChoiceResult.value.html","deprecated":false},{"id":"namespace_usethemechoiceresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseThemeChoiceResult.local","file":"src/hooks/theme/useThemeChoice.ts","doc":"This browser's own choice, which an account without one takes.","url":"./src/hooks/theme/useThemeChoice.ts/~/UseThemeChoiceResult.local.html","deprecated":false},{"id":"namespace_usethemechoiceresult","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"UseThemeChoiceResult.set","file":"src/hooks/theme/useThemeChoice.ts","doc":"Applies next, stores it here, and saves it to the account when signed in.","url":"./src/hooks/theme/useThemeChoice.ts/~/UseThemeChoiceResult.set.html","deprecated":false},{"id":"namespace_usethemechoice","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useThemeChoice","file":"src/hooks/theme/useThemeChoice.ts","doc":"Returns the half of the theme spec describes. An unknown stored value, such as \"default\", which \"smooth\" was once stored as, reads as no choice.","url":"./src/hooks/theme/useThemeChoice.ts/~/useThemeChoice.html","deprecated":false},{"id":"namespace_usews","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useWS","file":"src/hooks/ws/useWS.ts","doc":"Returns the connection's status, the live votes, likes, new and deleted dumps and playlists, the unread count, and the functions that vote and like. A component using it re-renders on every change to any of them.","url":"./src/hooks/ws/useWS.ts/~/useWS.html","deprecated":false},{"id":"namespace_usewschat","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useWSChat","file":"src/hooks/ws/useWS.ts","doc":"Returns the chat's messages, typing and read state. A component using it re-renders with every message and typing change, so a component that needs only the unread count still pays for them.","url":"./src/hooks/ws/useWS.ts/~/useWSChat.html","deprecated":false},{"id":"namespace_usewspresence","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useWSPresence","file":"src/hooks/ws/useWS.ts","doc":"Returns who is online, for the presence row.","url":"./src/hooks/ws/useWS.ts/~/useWSPresence.html","deprecated":false},{"id":"namespace_usewsevent","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useWSEvent","file":"src/hooks/ws/useWS.ts","doc":"Calls handler with every event of kind the socket brings, as it arrives, for as long as the component is mounted. The handler applies it to what the component fetched, through state setters: it runs outside render, and always as the latest render defined it. The list sync hooks, the dump and playlist pages, the profile, the bell and the categories use it.","url":"./src/hooks/ws/useWS.ts/~/useWSEvent.html","deprecated":false},{"id":"namespace_useonreconnect","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"useOnReconnect","file":"src/hooks/ws/useWS.ts","doc":"Calls callback after each reconnection of the socket, never on the first connection, for the component to fetch again what it may have missed while the socket was down. The live lists and pages use it.","url":"./src/hooks/ws/useWS.ts/~/useOnReconnect.html","deprecated":false},{"id":"namespace_loadcatalog","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"loadCatalog","file":"src/i18n.ts","doc":"Loads the messages of locale, the detected one by default, then activates it and stores it for the next visit. There is no language switch in the interface yet, so the stored one comes from the browser's language.","url":"./src/i18n.ts/~/loadCatalog.html","deprecated":false},{"id":"namespace_authorize","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"Authorize","file":"src/pages/Authorize.tsx","doc":"Renders /authorize?client_id=&redirect_uri=&state=&code_challenge=&nonce=. A signed-out visitor signs in first and comes back. The page names the instance asking (GET /api/oauth/clients) and what it will receive; once the user continues, or at once if they already did before, it gets a code (POST /api/oauth/codes) and goes back to the instance with it. An account that itself comes from another instance can't be used from here.","url":"./src/pages/Authorize.tsx/~/Authorize.html","deprecated":false},{"id":"namespace_community","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"Community","file":"src/pages/Community.tsx","doc":"Renders /community and /community/:view, from GET /api/community. A view no period names is NotFound.","url":"./src/pages/Community.tsx/~/Community.html","deprecated":false},{"id":"namespace_dump","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"Dump","file":"src/pages/Dump.tsx","doc":"Renders /@:username/dumps/:slug, for anyone who may see the dump: a private dump answers 404 to anyone but its poster. The dump comes from GET /api/users/@:username/dumps/:slug, or from the navigation's state when DumpEdit or a title edit here just saved it. Reached by a former name or slug, the URL takes the current ones. Its comments, related dumps and playlists come from their own endpoints once it is loaded, and the socket's events keep them current; a reconnection fetches them and the dump again. A dump deleted, or made private by its poster, while someone else views it gives way to a notice. The poster and moderators can edit the title and the note in place, and get a link to DumpEdit for the rest.","url":"./src/pages/Dump.tsx/~/Dump.html","deprecated":false},{"id":"namespace_dumpedit","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"DumpEdit","file":"src/pages/DumpEdit.tsx","doc":"Renders /@:username/dumps/:slug/edit, for the dump's poster and moderators; anyone else signed in gets an error rather than a form the API would refuse to save. The dump comes from GET /api/users/@:username/dumps/:slug, which answers a former slug too, and the URL then takes the current one. The thumbnail, the preview refresh and the deletion apply at once, and the form's other fields on \"Save\", which goes back to the dump's page, at its new path if the slug changed. A deletion goes to the index.","url":"./src/pages/DumpEdit.tsx/~/DumpEdit.html","deprecated":false},{"id":"namespace_federationcallback","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"FederationCallback","file":"src/pages/FederationCallback.tsx","doc":"Renders /federation/callback?code=&state=. It finishes the sign-in (POST /api/federation/sessions) if this tab started it (startedHere), and once: a code works only once, and a second request would fail the sign-in. On success the user lands on /, signed in.","url":"./src/pages/FederationCallback.tsx/~/FederationCallback.html","deprecated":false},{"id":"namespace_indexprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"IndexProps","file":"src/pages/Index.tsx","doc":"Passed to Index by the router, from the path.","url":"./src/pages/Index.tsx/~/IndexProps.html","deprecated":false},{"id":"namespace_indexprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"IndexProps.categorySlug","file":"src/pages/Index.tsx","doc":"Without it, the feed holds every dump. An unknown slug renders 404.","url":"./src/pages/Index.tsx/~/IndexProps.categorySlug.html","deprecated":false},{"id":"namespace_indexprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"IndexProps.feedTab","file":"src/pages/Index.tsx","doc":"The tab the path names, or none for the viewer's default one.","url":"./src/pages/Index.tsx/~/IndexProps.feedTab.html","deprecated":false},{"id":"namespace_indexprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"IndexProps.followView","file":"src/pages/Index.tsx","doc":"The view of the \"follow\" tab the path names, the users without one.","url":"./src/pages/Index.tsx/~/IndexProps.followView.html","deprecated":false},{"id":"namespace_index","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"Index","file":"src/pages/Index.tsx","doc":"Renders /, /:feedTab, /:categorySlug and /:categorySlug/:feedTab, for anyone, the \"follow\" tab, and its /follow/playlists, for a signed-in user only. The feed comes from GET /api/dumps, or GET /api/dumps?category=, a page at a time, and the \"hot\", \"new\" and \"journal\" tabs share it. WSContext adds the dumps posted since, or brought into the feed by an edit, by date, the live vote counts, and who's online. The router keys the page by category, so switching tabs keeps the feed and switching categories refetches it. It also opens the dump creation modal on a link shared from Android (?share_url=).","url":"./src/pages/Index.tsx/~/Index.html","deprecated":false},{"id":"namespace_manage","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"Manage","file":"src/pages/Manage.tsx","doc":"Renders the managers of the dump and the playlist categories, and the instances the site trusts or blocks, each to those who hold its permission, which the API checks again, the instances only while federated sign-in goes at least one way; without either, the page isn't found.","url":"./src/pages/Manage.tsx/~/Manage.html","deprecated":false},{"id":"namespace_notfound","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"NotFound","file":"src/pages/NotFound.tsx","doc":"Renders the 404 page, with a link home. Anyone may see it.","url":"./src/pages/NotFound.tsx/~/NotFound.html","deprecated":false},{"id":"namespace_notifications","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"Notifications","file":"src/pages/Notifications.tsx","doc":"Renders /notifications, for a signed-in user, a page at a time as the list scrolls. Opening the page marks every notification read on the server, and so does each that arrives while it is open. The unread ones stay highlighted until the page is left. Going back restores the list and the scroll, with what came in meanwhile on top.","url":"./src/pages/Notifications.tsx/~/Notifications.html","deprecated":false},{"id":"namespace_playlistdetailprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PlaylistDetailProps","file":"src/pages/PlaylistDetail.tsx","doc":"Passed to PlaylistDetail by App's route.","url":"./src/pages/PlaylistDetail.tsx/~/PlaylistDetailProps.html","deprecated":false},{"id":"namespace_playlistdetailprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PlaylistDetailProps.editing","file":"src/pages/PlaylistDetail.tsx","doc":"Set at /edit, where the editor is open.","url":"./src/pages/PlaylistDetail.tsx/~/PlaylistDetailProps.editing.html","deprecated":false},{"id":"namespace_playlistdetail","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"PlaylistDetail","file":"src/pages/PlaylistDetail.tsx","doc":"Renders /@:username/playlists/:slug, for anyone who may see the playlist: a private one only to its owner. usePlaylist loads it, by a former name or slug too, and keeps it live. Its owner, or a user with playlist:moderate, can drag its dumps into a new order and remove one, with a short window to undo, edit its title and description in place, and edit the rest or delete it in the editor that opens over its header at /@:username/playlists/:slug/edit. Both paths render the page at the same place, so opening the editor keeps the playlist loaded. Anyone else there gets the page, or is asked to sign in first.","url":"./src/pages/PlaylistDetail.tsx/~/PlaylistDetail.html","deprecated":false},{"id":"namespace_playlists","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"Playlists","file":"src/pages/Playlists.tsx","doc":"Renders the list for the route's category, or every public playlist without one, on the tab the URL's query names. Each category's list on each tab is another, which the page mounts afresh. A slug that names no playlist category, once the categories have loaded, is a page not found.","url":"./src/pages/Playlists.tsx/~/Playlists.html","deprecated":false},{"id":"namespace_resetpassword","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"ResetPassword","file":"src/pages/ResetPassword.tsx","doc":"Renders /reset-password, for anyone: the request for a reset link, or, with the link's ?token=, the new password. It doesn't sign the user in: a success links to /login.","url":"./src/pages/ResetPassword.tsx/~/ResetPassword.html","deprecated":false},{"id":"namespace_restrictedguestprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"RestrictedGuestProps","file":"src/pages/RestrictedGuest.tsx","doc":"Passed to RestrictedGuest by App, around a route's page.","url":"./src/pages/RestrictedGuest.tsx/~/RestrictedGuestProps.html","deprecated":false},{"id":"namespace_restrictedguestprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RestrictedGuestProps.children","file":"src/pages/RestrictedGuest.tsx","doc":"","url":"./src/pages/RestrictedGuest.tsx/~/RestrictedGuestProps.children.html","deprecated":false},{"id":"namespace_restrictedguest","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"RestrictedGuest","file":"src/pages/RestrictedGuest.tsx","doc":"Renders children when no one is signed in, and redirects otherwise: to the page a ?next= names (nextPath), or to /.","url":"./src/pages/RestrictedGuest.tsx/~/RestrictedGuest.html","deprecated":false},{"id":"namespace_restrictedloggedinprops","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"RestrictedLoggedInProps","file":"src/pages/RestrictedLoggedIn.tsx","doc":"Passed to RestrictedLoggedIn by App, around a route's page.","url":"./src/pages/RestrictedLoggedIn.tsx/~/RestrictedLoggedInProps.html","deprecated":false},{"id":"namespace_restrictedloggedinprops","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"RestrictedLoggedInProps.children","file":"src/pages/RestrictedLoggedIn.tsx","doc":"","url":"./src/pages/RestrictedLoggedIn.tsx/~/RestrictedLoggedInProps.children.html","deprecated":false},{"id":"namespace_restrictedloggedin","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"RestrictedLoggedIn","file":"src/pages/RestrictedLoggedIn.tsx","doc":"Renders children when someone is signed in, and otherwise replaces the page with /login, which comes back to it once signed in: a digest's link to /notifications opened signed out lands there after all.","url":"./src/pages/RestrictedLoggedIn.tsx/~/RestrictedLoggedIn.html","deprecated":false},{"id":"namespace_search","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"Search","file":"src/pages/Search.tsx","doc":"Renders /search?q= and /search/:searchTab?q=, for anyone. The results come from GET /api/search, signed in when the viewer is, so they find their own private dumps and playlists too. The dumps load a page at a time as the \"dumps\" tab scrolls. A new q aborts the search under way. The socket keeps the dumps and playlists found live, as edited or deleted, but adds none; a reconnection runs the search again, for every page of dumps loaded.On the \"dumps\" and \"playlists\" tabs, a menu narrows the results to a category of their kind, kept in the URL's ?category=, which another tab drops.","url":"./src/pages/Search.tsx/~/Search.html","deprecated":false},{"id":"namespace_settings","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"Settings","file":"src/pages/Settings.tsx","doc":"Renders /settings, signed in only: the username, which only a moderator changes (ProfileManageTab), the password change, which opens ChangePasswordModal, the other instances the account signs in to (GrantList) unless it may sign in to none, and the settings, each saved as soon as it is clicked. An account from another instance changes its password there. The style, color scheme and digests are saved to the account; the default feed tab and sounds, for now, to this browser.","url":"./src/pages/Settings.tsx/~/Settings.html","deprecated":false},{"id":"namespace_unsubscribe","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"Unsubscribe","file":"src/pages/Unsubscribe.tsx","doc":"Renders /unsubscribe?token=, for anyone holding a digest's link. It asks before turning the digest off, since mail scanners open every link in an email, then posts the token to POST /api/unsubscribe.","url":"./src/pages/Unsubscribe.tsx/~/Unsubscribe.html","deprecated":false},{"id":"namespace_userlogin","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"UserLogin","file":"src/pages/UserLogin.tsx","doc":"Renders /login, for the signed out. A sign-in lands on the page ?next= names, or /, and \"Forgot password?\" leads to /reset-password, which asks for a reset link. Users of another instance sign in through FederatedSignIn, unless the instance takes none.","url":"./src/pages/UserLogin.tsx/~/UserLogin.html","deprecated":false},{"id":"namespace_userpublicprofile","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"UserPublicProfile","file":"src/pages/UserPublicProfile.tsx","doc":"Renders /@:username and its tabs, /@:username/:tab, and the follow tab's view /@:username/follow/playlists, for anyone. useProfile loads the user, by a former name or another case too, and the URL then takes the current one; each tab loads its own lists, by the user's id, when shown. On their own profile, users edit their avatar, description and email, and create invites. The \"manage\" tab, another user's role and name, is for those who hold user:manage. A tab or view the profile hasn't is NotFound.","url":"./src/pages/UserPublicProfile.tsx/~/UserPublicProfile.html","deprecated":false},{"id":"namespace_userregister","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"UserRegister","file":"src/pages/UserRegister.tsx","doc":"Renders /register?token=, for the signed out. It checks the invite before showing the form, and signs the new user in on success. A user of another instance joins with that account instead, through FederatedSignIn, unless the instance takes none.","url":"./src/pages/UserRegister.tsx/~/UserRegister.html","deprecated":false},{"id":"namespace_remembersignin","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"rememberSignIn","file":"src/utils/auth/federation.ts","doc":"Keeps the state of the sign-in that authorizeUrl starts.","url":"./src/utils/auth/federation.ts/~/rememberSignIn.html","deprecated":false},{"id":"namespace_startedhere","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"startedHere","file":"src/utils/auth/federation.ts","doc":"Returns whether state is that of the sign-in this tab started.","url":"./src/utils/auth/federation.ts/~/startedHere.html","deprecated":false},{"id":"namespace_forgetsignin","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"forgetSignIn","file":"src/utils/auth/federation.ts","doc":"Forgets the sign-in this tab started, once it is being finished.","url":"./src/utils/auth/federation.ts/~/forgetSignIn.html","deprecated":false},{"id":"namespace_isselfhost","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isSelfHost","file":"src/utils/auth/home.ts","doc":"Checks whether host, as a handle writes it, is this instance's: its API's, which handles carry, or its pages'. Another instance writes this one's users with it.","url":"./src/utils/auth/home.ts/~/isSelfHost.html","deprecated":false},{"id":"namespace_homehost","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"homeHost","file":"src/utils/auth/home.ts","doc":"Returns the host of handle's home instance, or undefined for a local user.","url":"./src/utils/auth/home.ts/~/homeHost.html","deprecated":false},{"id":"namespace_homeurl","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"homeUrl","file":"src/utils/auth/home.ts","doc":"Returns a link to path on handle's home instance, their profile there by default, or null for a local user. The host in a handle is the home's API, not necessarily its pages, so the link goes through GET /api/users/:key/home, which redirects to them.","url":"./src/utils/auth/home.ts/~/homeUrl.html","deprecated":false},{"id":"namespace_loginpath","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"loginPath","file":"src/utils/auth/next.ts","doc":"Returns the /login path that comes back to path after signing in, a path on this site with its query.","url":"./src/utils/auth/next.ts/~/loginPath.html","deprecated":false},{"id":"namespace_nextpath","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"nextPath","file":"src/utils/auth/next.ts","doc":"Returns the next of params when it is a path on this site, or null. Anything else, //elsewhere.example included, is ignored, so a link can't send someone off the site through the login page.","url":"./src/utils/auth/next.ts/~/nextPath.html","deprecated":false},{"id":"namespace_can","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"can","file":"src/utils/auth/permissions.ts","doc":"Checks whether user has permission. A null user, for the signed out, has none. The server checks again, so this only decides what to show.","url":"./src/utils/auth/permissions.ts/~/can.html","deprecated":false},{"id":"namespace_session","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"Session","file":"src/utils/auth/storage.ts","doc":"Held by AuthProvider and stored here. It is the AuthResponse of a sign-in or sign-up, except that one stored before media tokens existed has none until AuthProvider fetches it. AuthProvider adds the user's settings once it has read them from the server, and useSettings keeps them current.","url":"./src/utils/auth/storage.ts/~/Session.html","deprecated":false},{"id":"namespace_auth_storage_key","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"AUTH_STORAGE_KEY","file":"src/utils/auth/storage.ts","doc":"The localStorage key of the session. AuthProvider listens for changes to it from other tabs.","url":"./src/utils/auth/storage.ts/~/AUTH_STORAGE_KEY.html","deprecated":false},{"id":"namespace_istokenexpired","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isTokenExpired","file":"src/utils/auth/storage.ts","doc":"Checks whether token, a JWT, has expired, without asking the server. An unreadable one counts as expired.","url":"./src/utils/auth/storage.ts/~/isTokenExpired.html","deprecated":false},{"id":"namespace_readstoredsession","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"readStoredSession","file":"src/utils/auth/storage.ts","doc":"Returns the stored session, or null. A session that is unreadable, expired or from before roles existed is removed from storage.","url":"./src/utils/auth/storage.ts/~/readStoredSession.html","deprecated":false},{"id":"namespace_storesession","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"storeSession","file":"src/utils/auth/storage.ts","doc":"Stores session, for every tab.","url":"./src/utils/auth/storage.ts/~/storeSession.html","deprecated":false},{"id":"namespace_forgetstoredsession","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"forgetStoredSession","file":"src/utils/auth/storage.ts","doc":"Forgets the stored session, but only if it still holds token. Another tab may have replaced it with fresh tokens from a password change, and a 401 for the old token here must not wipe those.","url":"./src/utils/auth/storage.ts/~/forgetStoredSession.html","deprecated":false},{"id":"namespace_readunsubscribecadence","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"readUnsubscribeCadence","file":"src/utils/auth/unsubscribe.ts","doc":"Returns the cadence token names, or null when it isn't an unsubscribe token at all.","url":"./src/utils/auth/unsubscribe.ts/~/readUnsubscribeCadence.html","deprecated":false},{"id":"namespace_storeddraft","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"StoredDraft","file":"src/utils/chat/draft.ts","doc":"Returned by readDraft to ChatModal, which passes it back to writeDraft.","url":"./src/utils/chat/draft.ts/~/StoredDraft.html","deprecated":false},{"id":"namespace_storeddraft","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"StoredDraft.draft","file":"src/utils/chat/draft.ts","doc":"","url":"./src/utils/chat/draft.ts/~/StoredDraft.draft.html","deprecated":false},{"id":"namespace_storeddraft","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"StoredDraft.replyTarget","file":"src/utils/chat/draft.ts","doc":"","url":"./src/utils/chat/draft.ts/~/StoredDraft.replyTarget.html","deprecated":false},{"id":"namespace_readdraft","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"readDraft","file":"src/utils/chat/draft.ts","doc":"Returns the stored draft of userId, or an empty one when there is none, userId is undefined, or storage is blocked.","url":"./src/utils/chat/draft.ts/~/readDraft.html","deprecated":false},{"id":"namespace_writedraft","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"writeDraft","file":"src/utils/chat/draft.ts","doc":"Stores value as the draft of userId, or removes it when it has neither text nor a reply target. Does nothing when userId is undefined.","url":"./src/utils/chat/draft.ts/~/writeDraft.html","deprecated":false},{"id":"namespace_count_from","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"COUNT_FROM","file":"src/utils/chat/message.ts","doc":"The length from which the composer and the edit box show their character counter, near VALIDATION.CHAT_MESSAGE_MAX.","url":"./src/utils/chat/message.ts/~/COUNT_FROM.html","deprecated":false},{"id":"namespace_sendable","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"sendable","file":"src/utils/chat/message.ts","doc":"Checks whether draft can be sent or saved. Like the server, it measures the trimmed text.","url":"./src/utils/chat/message.ts/~/sendable.html","deprecated":false},{"id":"namespace_messagetextclass","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"messageTextClass","file":"src/utils/chat/message.ts","doc":"Returns the class for the text of a sent or pending message. A message of nothing but a few emoji gets the one that shows it large.","url":"./src/utils/chat/message.ts/~/messageTextClass.html","deprecated":false},{"id":"namespace_snippet","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"snippet","file":"src/utils/chat/message.ts","doc":"Returns body as one line of plain text, for the reply bar above the composer and the reply line above a message.","url":"./src/utils/chat/message.ts/~/snippet.html","deprecated":false},{"id":"namespace_mentionsuser","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"mentionsUser","file":"src/utils/chat/text.ts","doc":"Checks whether body @mentions username, ignoring case, with the pattern the server uses for mention notifications, this instance's own host included (localHandle). WSProvider uses it to pick the chime, and ChatModal to highlight the message.","url":"./src/utils/chat/text.ts/~/mentionsUser.html","deprecated":false},{"id":"namespace_issameday","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isSameDay","file":"src/utils/chat/time.ts","doc":"Checks whether a and b fall on the same local day.","url":"./src/utils/chat/time.ts/~/isSameDay.html","deprecated":false},{"id":"namespace_daylabel","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"dayLabel","file":"src/utils/chat/time.ts","doc":"Returns the label of the day separator for date. It is \"Today\", \"Yesterday\", or the full date, with the year only when it isn't this one.","url":"./src/utils/chat/time.ts/~/dayLabel.html","deprecated":false},{"id":"namespace_clocktime","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"clockTime","file":"src/utils/chat/time.ts","doc":"Returns the hours and minutes of date, without the day period (\"PM\") so it fits the narrow space beside a grouped message. Its tooltip shows the full time.","url":"./src/utils/chat/time.ts/~/clockTime.html","deprecated":false},{"id":"namespace_dumpdraft","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"DumpDraft","file":"src/utils/dump/draft.ts","doc":"Saved by DumpCreateModal on every change, and restored when it next opens without a shared link. Posting the dump clears it.","url":"./src/utils/dump/draft.ts/~/DumpDraft.html","deprecated":false},{"id":"namespace_dumpdraft","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpDraft.url","file":"src/utils/dump/draft.ts","doc":"As typed, not yet normalized.","url":"./src/utils/dump/draft.ts/~/DumpDraft.url.html","deprecated":false},{"id":"namespace_dumpdraft","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpDraft.title","file":"src/utils/dump/draft.ts","doc":"","url":"./src/utils/dump/draft.ts/~/DumpDraft.title.html","deprecated":false},{"id":"namespace_dumpdraft","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpDraft.titleFromUser","file":"src/utils/dump/draft.ts","doc":"Whether the poster typed title. When not, the modal takes the title from the link's preview again.","url":"./src/utils/dump/draft.ts/~/DumpDraft.titleFromUser.html","deprecated":false},{"id":"namespace_dumpdraft","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpDraft.comment","file":"src/utils/dump/draft.ts","doc":"In Markdown.","url":"./src/utils/dump/draft.ts/~/DumpDraft.comment.html","deprecated":false},{"id":"namespace_dumpdraft","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpDraft.isPublic","file":"src/utils/dump/draft.ts","doc":"","url":"./src/utils/dump/draft.ts/~/DumpDraft.isPublic.html","deprecated":false},{"id":"namespace_dumpdraft","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"DumpDraft.categoryIds","file":"src/utils/dump/draft.ts","doc":"","url":"./src/utils/dump/draft.ts/~/DumpDraft.categoryIds.html","deprecated":false},{"id":"namespace_empty_dump_draft","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"EMPTY_DUMP_DRAFT","file":"src/utils/dump/draft.ts","doc":"The modal's starting values, when no draft is restored.","url":"./src/utils/dump/draft.ts/~/EMPTY_DUMP_DRAFT.html","deprecated":false},{"id":"namespace_isdumpdraftempty","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isDumpDraftEmpty","file":"src/utils/dump/draft.ts","doc":"Checks whether draft holds nothing worth restoring. A title taken from the preview doesn't count, since the preview gives it back.","url":"./src/utils/dump/draft.ts/~/isDumpDraftEmpty.html","deprecated":false},{"id":"namespace_loaddumpdraft","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"loadDumpDraft","file":"src/utils/dump/draft.ts","doc":"Returns the stored draft, or null when there is none worth restoring or storage is blocked. A field that doesn't parse takes its empty value.","url":"./src/utils/dump/draft.ts/~/loadDumpDraft.html","deprecated":false},{"id":"namespace_savedumpdraft","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"saveDumpDraft","file":"src/utils/dump/draft.ts","doc":"Stores draft, or removes the stored one when draft is empty. A failure is silent: the draft is a convenience, never a precondition for posting.","url":"./src/utils/dump/draft.ts/~/saveDumpDraft.html","deprecated":false},{"id":"namespace_cleardumpdraft","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"clearDumpDraft","file":"src/utils/dump/draft.ts","doc":"Removes the stored draft, once the dump is posted or the poster chose to start afresh.","url":"./src/utils/dump/draft.ts/~/clearDumpDraft.html","deprecated":false},{"id":"namespace_skin_tone_key","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"SKIN_TONE_KEY","file":"src/utils/editor/skinTone.ts","doc":"Names the skin tone in localStorage. EmojiPickerPopup writes under it.","url":"./src/utils/editor/skinTone.ts/~/SKIN_TONE_KEY.html","deprecated":false},{"id":"namespace_readskintone","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"readSkinTone","file":"src/utils/editor/skinTone.ts","doc":"Returns the stored skin tone, or none when there is none or storage is blocked. The stored value is not checked against frimousse's tones.","url":"./src/utils/editor/skinTone.ts/~/readSkinTone.html","deprecated":false},{"id":"namespace_insidecode","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"insideCode","file":"src/utils/editor/text.ts","doc":"Checks whether the caret at the end of textBefore sits inside Markdown code, an open ``` fence or an unclosed span on the current line. The mention and emoji autocompletes stay closed there, since `@bob` and `:smile` are literal text in code.","url":"./src/utils/editor/text.ts/~/insideCode.html","deprecated":false},{"id":"namespace_isemojionly","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isEmojiOnly","file":"src/utils/editor/text.ts","doc":"Checks whether text is nothing but max emoji at most, which the chat shows large, as in \"🎉\" or \"👍👍\". Emoji are counted as graphemes, so a family or a flag counts once.","url":"./src/utils/editor/text.ts/~/isEmojiOnly.html","deprecated":false},{"id":"namespace_hotscore","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"hotScore","file":"src/utils/feed/hotScore.ts","doc":"Returns the score that DumpFeed and composeJournal sort by, highest first. It grows with the votes and decays with the age in hours, so a new dump without votes can outrank an old popular one. The server doesn't rank, so only the loaded dumps are ranked.","url":"./src/utils/feed/hotScore.ts/~/hotScore.html","deprecated":false},{"id":"namespace_journalshape","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"JournalShape","file":"src/utils/feed/journalLayout.ts","doc":"The grid span of a tile, which JournalCard turns into a CSS class. A feature spans 2×2 cells, a wide 2×1, a tall 1×2 and a square 1×1. Whether the tile shows an image, a quote or text depends on the dump alone.","url":"./src/utils/feed/journalLayout.ts/~/JournalShape.html","deprecated":false},{"id":"namespace_journalentry","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"JournalEntry","file":"src/utils/feed/journalLayout.ts","doc":"Returned by composeJournal within a JournalBlock.","url":"./src/utils/feed/journalLayout.ts/~/JournalEntry.html","deprecated":false},{"id":"namespace_journalentry","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"JournalEntry.dump","file":"src/utils/feed/journalLayout.ts","doc":"","url":"./src/utils/feed/journalLayout.ts/~/JournalEntry.dump.html","deprecated":false},{"id":"namespace_journalentry","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"JournalEntry.shape","file":"src/utils/feed/journalLayout.ts","doc":"","url":"./src/utils/feed/journalLayout.ts/~/JournalEntry.shape.html","deprecated":false},{"id":"namespace_journalblock","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"JournalBlock","file":"src/utils/feed/journalLayout.ts","doc":"Returned by composeJournal. JournalFeed renders each block as its own grid, with a rule between two blocks.","url":"./src/utils/feed/journalLayout.ts/~/JournalBlock.html","deprecated":false},{"id":"namespace_journalblock","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"JournalBlock.key","file":"src/utils/feed/journalLayout.ts","doc":"The id of the block's first dump, stable as more pages load.","url":"./src/utils/feed/journalLayout.ts/~/JournalBlock.key.html","deprecated":false},{"id":"namespace_journalblock","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"JournalBlock.entries","file":"src/utils/feed/journalLayout.ts","doc":"In reading order.","url":"./src/utils/feed/journalLayout.ts/~/JournalBlock.entries.html","deprecated":false},{"id":"namespace_hasthumbnail","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"hasThumbnail","file":"src/utils/feed/journalLayout.ts","doc":"Checks whether dump has an image to show: an uploaded thumbnail, an image, video or audio file, or a link preview's thumbnail. Only such dumps get the large tiles, and JournalCard shows them as image tiles.","url":"./src/utils/feed/journalLayout.ts/~/hasThumbnail.html","deprecated":false},{"id":"namespace_hasquote","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"hasQuote","file":"src/utils/feed/journalLayout.ts","doc":"Checks whether dump has a non-blank note, which JournalCard shows as a pull-quote when the dump has no image.","url":"./src/utils/feed/journalLayout.ts/~/hasQuote.html","deprecated":false},{"id":"namespace_composejournal","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"composeJournal","file":"src/utils/feed/journalLayout.ts","doc":"Sorts dumps by hotScore and lays them out as a mosaic whose rows all close, cut into blocks. JournalFeed calls it on every change of the feed.A block ends once it holds 12 tiles, at the next row that starts empty and that no tall tile reaches into. The tile opening the next block is made a feature, or a wide without an image, which always fits a row that starts empty. The layout depends only on the ranking, so when the next page appends dumps that rank lower, only the last block changes.","url":"./src/utils/feed/journalLayout.ts/~/composeJournal.html","deprecated":false},{"id":"namespace_pagedlist","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"PagedList","file":"src/utils/feed/pagedList.ts","doc":"Held for a list by usePagedList, or by a page that loads it along with more, as the search page does. useLoadMore loads the pages after page.","url":"./src/utils/feed/pagedList.ts/~/PagedList.html","deprecated":false},{"id":"namespace_pagedlist","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PagedList.items","file":"src/utils/feed/pagedList.ts","doc":"","url":"./src/utils/feed/pagedList.ts/~/PagedList.items.html","deprecated":false},{"id":"namespace_pagedlist","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PagedList.hasMore","file":"src/utils/feed/pagedList.ts","doc":"","url":"./src/utils/feed/pagedList.ts/~/PagedList.hasMore.html","deprecated":false},{"id":"namespace_pagedlist","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PagedList.page","file":"src/utils/feed/pagedList.ts","doc":"Loading more carries on from this page, the last loaded.","url":"./src/utils/feed/pagedList.ts/~/PagedList.page.html","deprecated":false},{"id":"namespace_pagedlist","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"PagedList.loadingMore","file":"src/utils/feed/pagedList.ts","doc":"","url":"./src/utils/feed/pagedList.ts/~/PagedList.loadingMore.html","deprecated":false},{"id":"namespace_firstpage","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"firstPage","file":"src/utils/feed/pagedList.ts","doc":"Returns the list holding only its first page, items.","url":"./src/utils/feed/pagedList.ts/~/firstPage.html","deprecated":false},{"id":"namespace_restoredlist","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"restoredList","file":"src/utils/feed/pagedList.ts","doc":"Returns the list as useFeedCache's cached restores it.","url":"./src/utils/feed/pagedList.ts/~/restoredList.html","deprecated":false},{"id":"namespace_canloadmore","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"canLoadMore","file":"src/utils/feed/pagedList.ts","doc":"Checks whether list has a next page to load now, which useLoadMore requires and useInfiniteScroll takes as enabled. A list not loaded yet is null.","url":"./src/utils/feed/pagedList.ts/~/canLoadMore.html","deprecated":false},{"id":"namespace_mapitems","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"mapItems","file":"src/utils/feed/pagedList.ts","doc":"Returns a setter of a list's items as a setter of the list, for the sync hooks, which edit items only.","url":"./src/utils/feed/pagedList.ts/~/mapItems.html","deprecated":false},{"id":"namespace_pageurl","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"pageUrl","file":"src/utils/feed/pagedList.ts","doc":"Returns url asking for page page, limit items long.","url":"./src/utils/feed/pagedList.ts/~/pageUrl.html","deprecated":false},{"id":"namespace_readpage","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"readPage","file":"src/utils/feed/pagedList.ts","doc":"Returns the page res answers, its items deserialized.","url":"./src/utils/feed/pagedList.ts/~/readPage.html","deprecated":false},{"id":"namespace_readfirstpage","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"readFirstPage","file":"src/utils/feed/pagedList.ts","doc":"Returns the first page res answers as a list, or an empty list when the server refuses it. The profile pages read their lists with it beside the user, whose failure alone fails the page.","url":"./src/utils/feed/pagedList.ts/~/readFirstPage.html","deprecated":false},{"id":"namespace_withfirst","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"withFirst","file":"src/utils/feed/pagedList.ts","doc":"Returns items with item first, or items as they are when it is already there, as when a list's own echo of a new item arrives after it.","url":"./src/utils/feed/pagedList.ts/~/withFirst.html","deprecated":false},{"id":"namespace_withinorder","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"withInOrder","file":"src/utils/feed/pagedList.ts","doc":"Returns items, in the order of compare as the API pages them, with item where that order puts it: before the first item that doesn't come before it. An item that comes after every one loaded is left to a later page, and items returned as they are, as they are when item is already there. usePlaylistListSync puts a new, newly visible or risen playlist in a list with it, whatever its order.","url":"./src/utils/feed/pagedList.ts/~/withInOrder.html","deprecated":false},{"id":"namespace_withbydate","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"withByDate","file":"src/utils/feed/pagedList.ts","doc":"Returns items, newest first, with item where its createdAt puts it, as withInOrder does. useDumpListSync puts a new or newly visible dump in a list with it.","url":"./src/utils/feed/pagedList.ts/~/withByDate.html","deprecated":false},{"id":"namespace_refetchpages","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"refetchPages","file":"src/utils/feed/pagedList.ts","doc":"Fetches pages 1 to pages of a list again, and resolves to their items, each once, and whether more follow. An item added between two pages' fetches shifts the later page by one, which would list an item twice. A live list calls it after a reconnection, through usePagedList's resync or, for the search's dumps, directly; it rejects when a page fails.","url":"./src/utils/feed/pagedList.ts/~/refetchPages.html","deprecated":false},{"id":"namespace_bandcampcontext","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"BandcampContext","file":"src/utils/player/bandcamp.ts","doc":"Passed to resolveBandcampQueue by its callers and copied onto every item of the queue, since the server's tracklist knows nothing of the dump.","url":"./src/utils/player/bandcamp.ts/~/BandcampContext.html","deprecated":false},{"id":"namespace_bandcampcontext","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"BandcampContext.dumpHref","file":"src/utils/player/bandcamp.ts","doc":"","url":"./src/utils/player/bandcamp.ts/~/BandcampContext.dumpHref.html","deprecated":false},{"id":"namespace_bandcampcontext","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"BandcampContext.embedUrl","file":"src/utils/player/bandcamp.ts","doc":"Lets PlayerProvider fall back to Bandcamp's iframe if the streams fail.","url":"./src/utils/player/bandcamp.ts/~/BandcampContext.embedUrl.html","deprecated":false},{"id":"namespace_bandcampcontext","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"BandcampContext.fallbackArtworkUrl","file":"src/utils/player/bandcamp.ts","doc":"Used only if the page carries no album art of its own.","url":"./src/utils/player/bandcamp.ts/~/BandcampContext.fallbackArtworkUrl.html","deprecated":false},{"id":"namespace_resolvebandcampqueue","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"resolveBandcampQueue","file":"src/utils/player/bandcamp.ts","doc":"Resolves the Bandcamp page pageUrl into one stream item per streamable track, through GET /api/remote/bandcamp, each carrying ctx. force bypasses the server's cache, for re-resolving once the signed URLs expire.","url":"./src/utils/player/bandcamp.ts/~/resolveBandcampQueue.html","deprecated":false},{"id":"namespace_fmt","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"fmt","file":"src/utils/player/duration.ts","doc":"Returns s seconds as m:ss, or 0:00 when s isn't finite, as a media element's duration is until its metadata loads.","url":"./src/utils/player/duration.ts/~/fmt.html","deprecated":false},{"id":"namespace_resolvestreamqueue","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"resolveStreamQueue","file":"src/utils/player/streamSources.ts","doc":"Re-resolves the whole queue that stream item came from, bypassing the server's cache. The promise rejects when the stream's type has no resolver here, or when its resolver fails.","url":"./src/utils/player/streamSources.ts/~/resolveStreamQueue.html","deprecated":false},{"id":"namespace_stream_stale_ms","kind":[{"char":"v","kind":"Variable","title":"Variable"}],"name":"STREAM_STALE_MS","file":"src/utils/player/streamSources.ts","doc":"How old a stream's signed URL may get before isStreamStale says so. Bandcamp's live about 24 hours, and this leaves room for a long listen.","url":"./src/utils/player/streamSources.ts/~/STREAM_STALE_MS.html","deprecated":false},{"id":"namespace_isstreamstale","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isStreamStale","file":"src/utils/player/streamSources.ts","doc":"Checks whether the signed URL of item is older than STREAM_STALE_MS. PlayerProvider refreshes a restored session's stream when it is, so that the first press of play doesn't stall.","url":"./src/utils/player/streamSources.ts/~/isStreamStale.html","deprecated":false},{"id":"namespace_remembervolume","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"rememberVolume","file":"src/utils/player/volume.ts","doc":"Remembers volume and muted for the next media element, and in localStorage when it is available.","url":"./src/utils/player/volume.ts/~/rememberVolume.html","deprecated":false},{"id":"namespace_storedvolume","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"storedVolume","file":"src/utils/player/volume.ts","doc":"Returns the volume and mute state last remembered, or full and unmuted.","url":"./src/utils/player/volume.ts/~/storedVolume.html","deprecated":false},{"id":"namespace_peakssource","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"PeaksSource","file":"src/utils/player/waveform.ts","doc":"Where a waveform's peaks come from: the server's for an uploaded file (dumpWaveformUrl), or the bytes of a local file, by its blob: URL.","url":"./src/utils/player/waveform.ts/~/PeaksSource.html","deprecated":false},{"id":"namespace_peakskey","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"peaksKey","file":"src/utils/player/waveform.ts","doc":"Returns the key loads keeps source's peaks under.","url":"./src/utils/player/waveform.ts/~/peaksKey.html","deprecated":false},{"id":"namespace_loadpeaks","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"loadPeaks","file":"src/utils/player/waveform.ts","doc":"Returns the peaks of source, from 0 to 1.","url":"./src/utils/player/waveform.ts/~/loadPeaks.html","deprecated":false},{"id":"namespace_embedlistid","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"embedListId","file":"src/utils/player/youtube.ts","doc":"Returns the id of the playlist embedUrl plays, or null. It reads both shapes the server's YouTube embeds take, /embed/videoseries?list=… for a bare playlist and /embed/<id>?list=… for a video opened in one.","url":"./src/utils/player/youtube.ts/~/embedListId.html","deprecated":false},{"id":"namespace_withjsapi","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"withJsApi","file":"src/utils/player/youtube.ts","doc":"Returns url with the parameters the IFrame Player API needs to drive the embed. enablejsapi can't be turned on after the iframe loads, so GlobalPlayer adds it to every playlist embed, whether or not the API script loads.","url":"./src/utils/player/youtube.ts/~/withJsApi.html","deprecated":false},{"id":"namespace_fetchplaylisttracks","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"fetchPlaylistTracks","file":"src/utils/player/youtube.ts","doc":"Returns the titles and lengths of the videos of playlist listId, from GET /api/remote/youtube, since the embed exposes neither.","url":"./src/utils/player/youtube.ts/~/fetchPlaylistTracks.html","deprecated":false},{"id":"namespace_parseapiresponse","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"parseAPIResponse","file":"src/utils/shared/api.ts","doc":"Returns raw as an API envelope. Only the success field is checked, so the payload's type is the caller's word.","url":"./src/utils/shared/api.ts/~/parseAPIResponse.html","deprecated":false},{"id":"namespace_friendlyfetcherror","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"friendlyFetchError","file":"src/utils/shared/api.ts","doc":"Returns the message to show for err, an error caught around a request. A TypeError means the request never reached the server (no network, CORS), and gets a message saying so. The server's own messages come through as they are.","url":"./src/utils/shared/api.ts/~/friendlyFetchError.html","deprecated":false},{"id":"namespace_expectok","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"expectOk","file":"src/utils/shared/api.ts","doc":"Returns the payload of res. In a form, the error it throws reaches useApiForm's submit, which shows it as the form's error.","url":"./src/utils/shared/api.ts/~/expectOk.html","deprecated":false},{"id":"namespace_dataor","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"dataOr","file":"src/utils/shared/api.ts","doc":"Returns the payload of res, or fallback when the response says success: false. readFirstPage reads the profile pages' lists with it, and the profile its invitees, so that a list the server refuses shows empty rather than failing the page.","url":"./src/utils/shared/api.ts/~/dataOr.html","deprecated":false},{"id":"namespace_charcountclass","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"charCountClass","file":"src/utils/shared/charCount.ts","doc":"Returns the counter's modifier class for len characters out of max, with a leading space so that it appends to text-editor-count. It warns from 85% of max and turns to danger at max.","url":"./src/utils/shared/charCount.ts/~/charCountClass.html","deprecated":false},{"id":"namespace_deserializedump","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"deserializeDump","file":"src/utils/shared/deserialize.ts","doc":"Returns raw as a Dump.","url":"./src/utils/shared/deserialize.ts/~/deserializeDump.html","deprecated":false},{"id":"namespace_hydratedump","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"hydrateDump","file":"src/utils/shared/deserialize.ts","doc":"Returns raw as a Dump, for useFeedCache, which reads it back untyped from sessionStorage.","url":"./src/utils/shared/deserialize.ts/~/hydrateDump.html","deprecated":false},{"id":"namespace_deserializedumpurlmatch","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"deserializeDumpUrlMatch","file":"src/utils/shared/deserialize.ts","doc":"Returns raw as a DumpUrlMatch.","url":"./src/utils/shared/deserialize.ts/~/deserializeDumpUrlMatch.html","deprecated":false},{"id":"namespace_deserializecategory","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"deserializeCategory","file":"src/utils/shared/deserialize.ts","doc":"Returns raw as a Category.","url":"./src/utils/shared/deserialize.ts/~/deserializeCategory.html","deprecated":false},{"id":"namespace_deserializepublicuser","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"deserializePublicUser","file":"src/utils/shared/deserialize.ts","doc":"Returns raw as a PublicUser.","url":"./src/utils/shared/deserialize.ts/~/deserializePublicUser.html","deprecated":false},{"id":"namespace_deserializeselfuser","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"deserializeSelfUser","file":"src/utils/shared/deserialize.ts","doc":"Returns raw as a SelfUser.","url":"./src/utils/shared/deserialize.ts/~/deserializeSelfUser.html","deprecated":false},{"id":"namespace_deserializeinvitee","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"deserializeInvitee","file":"src/utils/shared/deserialize.ts","doc":"Returns raw as an Invitee.","url":"./src/utils/shared/deserialize.ts/~/deserializeInvitee.html","deprecated":false},{"id":"namespace_deserializeauthresponse","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"deserializeAuthResponse","file":"src/utils/shared/deserialize.ts","doc":"Returns raw as an AuthResponse.","url":"./src/utils/shared/deserialize.ts/~/deserializeAuthResponse.html","deprecated":false},{"id":"namespace_deserializecomment","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"deserializeComment","file":"src/utils/shared/deserialize.ts","doc":"Returns raw as a Comment.","url":"./src/utils/shared/deserialize.ts/~/deserializeComment.html","deprecated":false},{"id":"namespace_deserializechatmessage","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"deserializeChatMessage","file":"src/utils/shared/deserialize.ts","doc":"Returns raw as a ChatMessage.","url":"./src/utils/shared/deserialize.ts/~/deserializeChatMessage.html","deprecated":false},{"id":"namespace_deserializeplaylist","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"deserializePlaylist","file":"src/utils/shared/deserialize.ts","doc":"Returns raw as a Playlist.","url":"./src/utils/shared/deserialize.ts/~/deserializePlaylist.html","deprecated":false},{"id":"namespace_hydrateplaylist","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"hydratePlaylist","file":"src/utils/shared/deserialize.ts","doc":"Returns raw as a Playlist, for useFeedCache, which reads it back untyped from sessionStorage.","url":"./src/utils/shared/deserialize.ts/~/hydratePlaylist.html","deprecated":false},{"id":"namespace_deserializeplaylistwithdumps","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"deserializePlaylistWithDumps","file":"src/utils/shared/deserialize.ts","doc":"Returns raw as a PlaylistWithDumps, its dumps included.","url":"./src/utils/shared/deserialize.ts/~/deserializePlaylistWithDumps.html","deprecated":false},{"id":"namespace_deserializeplaylistmembership","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"deserializePlaylistMembership","file":"src/utils/shared/deserialize.ts","doc":"Returns raw as a PlaylistMembership.","url":"./src/utils/shared/deserialize.ts/~/deserializePlaylistMembership.html","deprecated":false},{"id":"namespace_deserializenotification","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"deserializeNotification","file":"src/utils/shared/deserialize.ts","doc":"Returns raw as a Notification.","url":"./src/utils/shared/deserialize.ts/~/deserializeNotification.html","deprecated":false},{"id":"namespace_hydratenotification","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"hydrateNotification","file":"src/utils/shared/deserialize.ts","doc":"Returns raw as a Notification, for useFeedCache, which reads it back untyped from sessionStorage.","url":"./src/utils/shared/deserialize.ts/~/hydrateNotification.html","deprecated":false},{"id":"namespace_deserializecommunitystats","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"deserializeCommunityStats","file":"src/utils/shared/deserialize.ts","doc":"Returns raw as CommunityStats.","url":"./src/utils/shared/deserialize.ts/~/deserializeCommunityStats.html","deprecated":false},{"id":"namespace_deserializecommunityfeed","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"deserializeCommunityFeed","file":"src/utils/shared/deserialize.ts","doc":"Returns raw as a CommunityFeed.","url":"./src/utils/shared/deserialize.ts/~/deserializeCommunityFeed.html","deprecated":false},{"id":"namespace_deserializefederationpeer","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"deserializeFederationPeer","file":"src/utils/shared/deserialize.ts","doc":"Returns raw as a FederationPeer.","url":"./src/utils/shared/deserialize.ts/~/deserializeFederationPeer.html","deprecated":false},{"id":"namespace_deserializefederationgrant","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"deserializeFederationGrant","file":"src/utils/shared/deserialize.ts","doc":"Returns raw as a FederationGrant.","url":"./src/utils/shared/deserialize.ts/~/deserializeFederationGrant.html","deprecated":false},{"id":"namespace_landingrequest","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"landingRequest","file":"src/utils/shared/earlyFetch.ts","doc":"Returns the URL the page at pathname loads first, as that page builds it, or null for a page that isn't started early: the feed of every dump, on any of its tabs, asks for its first page, and a dump's page for the dump. The other pages wait for their code, as before.","url":"./src/utils/shared/earlyFetch.ts/~/landingRequest.html","deprecated":false},{"id":"namespace_startlandingrequest","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"startLandingRequest","file":"src/utils/shared/earlyFetch.ts","doc":"Sends the request landingRequest names for pathname, with the stored session's token as authFetch would, and keeps its response for takeEarly. It never throws: a request that fails does so in the hands of the page that takes it, as its own would.","url":"./src/utils/shared/earlyFetch.ts/~/startLandingRequest.html","deprecated":false},{"id":"namespace_takeearly","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"takeEarly","file":"src/utils/shared/earlyFetch.ts","doc":"Returns the response of the request started for url, once and to the session it was sent as, or undefined when there is none, or none recent enough: the caller then sends its own. authFetch asks it for every GET.","url":"./src/utils/shared/earlyFetch.ts/~/takeEarly.html","deprecated":false},{"id":"namespace_clearearlyrequests","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"clearEarlyRequests","file":"src/utils/shared/earlyFetch.ts","doc":"Forgets the requests started, between the tests' cases.","url":"./src/utils/shared/earlyFetch.ts/~/clearEarlyRequests.html","deprecated":false},{"id":"namespace_fetchpublicuser","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"fetchPublicUser","file":"src/utils/shared/fetchPublicUser.ts","doc":"Returns GET /api/users/@:username, for the profile, which fails as a whole when it does. username may be a former name, or the name in another case: the user comes back with their current one, which the profile puts in its URL. It is fetched afresh even when the lists come from useFeedCache.","url":"./src/utils/shared/fetchPublicUser.ts/~/fetchPublicUser.html","deprecated":false},{"id":"namespace_formatbytes","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"formatBytes","file":"src/utils/shared/format.ts","doc":"Returns bytes as a size in bytes, kilobytes or megabytes, where a kilobyte is 1024 bytes, in the app's language (\"1.5 kB\", \"1,5 ko\"). Intl names the units, so they follow the language without a catalog.","url":"./src/utils/shared/format.ts/~/formatBytes.html","deprecated":false},{"id":"namespace_titlefromfilename","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"titleFromFileName","file":"src/utils/shared/format.ts","doc":"Returns the file name name as the title the dump creation dialog proposes. The extension goes, since the dump keeps its MIME type, and runs of underscores become spaces, so holiday_photo-01.final.jpg reads as holiday photo-01.final. A name that is only an extension (.gitignore) stays as it is.","url":"./src/utils/shared/format.ts/~/titleFromFileName.html","deprecated":false},{"id":"namespace_loadstate","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"LoadState","file":"src/utils/shared/loadState.ts","doc":"Held by a page or hook for what it fetches, as useFetchState returns it, and passed to ListState. L is what the loaded state carries besides its status, as { data: T } for useFetchState or a feed's page fields.","url":"./src/utils/shared/loadState.ts/~/LoadState.html","deprecated":false},{"id":"namespace_canproxyimage","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"canProxyImage","file":"src/utils/shared/proxyImage.ts","doc":"Checks whether url points at another site, where proxying it could help. Thumbnail retries through the proxy only then, since the site's own files and thumbnails would fail the same way again.","url":"./src/utils/shared/proxyImage.ts/~/canProxyImage.html","deprecated":false},{"id":"namespace_proxyimageoptions","kind":[{"char":"I","kind":"Interface","title":"Interface"}],"name":"ProxyImageOptions","file":"src/utils/shared/proxyImage.ts","doc":"Passed to proxyImageUrl by Thumbnail to retry a failed image.","url":"./src/utils/shared/proxyImage.ts/~/ProxyImageOptions.html","deprecated":false},{"id":"namespace_proxyimageoptions","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"ProxyImageOptions.force","file":"src/utils/shared/proxyImage.ts","doc":"Proxies an HTTPS URL too, for a retry after a direct load failed, usually on hotlink protection.","url":"./src/utils/shared/proxyImage.ts/~/ProxyImageOptions.force.html","deprecated":false},{"id":"namespace_proxyimageurl","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"proxyImageUrl","file":"src/utils/shared/proxyImage.ts","doc":"Returns url routed through GET /api/remote/image, or unchanged when it needs no proxy. Only an HTTP URL is proxied by default, so that an HTTPS page doesn't block it as mixed content. A relative or localhost URL is never proxied.","url":"./src/utils/shared/proxyImage.ts/~/proxyImageUrl.html","deprecated":false},{"id":"namespace_relativetime","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"relativeTime","file":"src/utils/shared/relativeTime.ts","doc":"Returns how long ago date was, as \"3 minutes ago\", in the current locale. It is computed at render, so the text only moves on when the caller re-renders. A month counts 30 days and a year 365. Every date shown is of something that happened, so one in the future, which only a clock ahead of this one can give, reads as \"now\".","url":"./src/utils/shared/relativeTime.ts/~/relativeTime.html","deprecated":false},{"id":"namespace_chimekind","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"ChimeKind","file":"src/utils/shared/sound.ts","doc":"Passed to playChime and previewChime to pick the sound.","url":"./src/utils/shared/sound.ts/~/ChimeKind.html","deprecated":false},{"id":"namespace_readsoundsenabled","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"readSoundsEnabled","file":"src/utils/shared/sound.ts","doc":"Returns whether sounds are on in this browser, which they are unless turned off. playChime checks it on every play.","url":"./src/utils/shared/sound.ts/~/readSoundsEnabled.html","deprecated":false},{"id":"namespace_writesoundsenabled","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"writeSoundsEnabled","file":"src/utils/shared/sound.ts","doc":"Stores whether sounds are on, for useSoundsEnabled's setter.","url":"./src/utils/shared/sound.ts/~/writeSoundsEnabled.html","deprecated":false},{"id":"namespace_playchime","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"playChime","file":"src/utils/shared/sound.ts","doc":"Plays the chime for a live event, unless sounds are off, another tab already chimed for eventId, or a chat blip played less than 4 seconds ago. The caller must pass an id that is the same in every tab, such as the message's.","url":"./src/utils/shared/sound.ts/~/playChime.html","deprecated":false},{"id":"namespace_previewchime","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"previewChime","file":"src/utils/shared/sound.ts","doc":"Plays the chime kind whatever the setting, for the profile page's settings to preview it. It is called from a click, which unlocks the audio.","url":"./src/utils/shared/sound.ts/~/previewChime.html","deprecated":false},{"id":"namespace_tintfor","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"tintFor","file":"src/utils/shared/thumbnailTint.ts","doc":"Returns the page's own colour when it declared a valid one, or else a hue drawn from seed or the hostname of url, so that every card gets a tint, even for a dump saved before colours were extracted.","url":"./src/utils/shared/thumbnailTint.ts/~/tintFor.html","deprecated":false},{"id":"namespace_initialsfor","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"initialsFor","file":"src/utils/shared/thumbnailTint.ts","doc":"Returns the letter drawn when there's no favicon to show, the first letter or digit of siteName, or else of the hostname of url, or \"?\".","url":"./src/utils/shared/thumbnailTint.ts/~/initialsFor.html","deprecated":false},{"id":"namespace_versioneddump","kind":[{"char":"T","kind":"TypeAlias","title":"Type Alias"}],"name":"VersionedDump","file":"src/utils/shared/urls.ts","doc":"Passed to dumpFileUrl and dumpThumbnailUrl, usually as a whole Dump. Without the dates, the URL carries no current version and the browser revalidates it.","url":"./src/utils/shared/urls.ts/~/VersionedDump.html","deprecated":false},{"id":"namespace_versioneddump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VersionedDump.id","file":"src/utils/shared/urls.ts","doc":"","url":"./src/utils/shared/urls.ts/~/VersionedDump.id.html","deprecated":false},{"id":"namespace_versioneddump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VersionedDump.fileSize","file":"src/utils/shared/urls.ts","doc":"","url":"./src/utils/shared/urls.ts/~/VersionedDump.fileSize.html","deprecated":false},{"id":"namespace_versioneddump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VersionedDump.createdAt","file":"src/utils/shared/urls.ts","doc":"","url":"./src/utils/shared/urls.ts/~/VersionedDump.createdAt.html","deprecated":false},{"id":"namespace_versioneddump","kind":[{"char":"p","kind":"Property","title":"Property"}],"name":"VersionedDump.updatedAt","file":"src/utils/shared/urls.ts","doc":"","url":"./src/utils/shared/urls.ts/~/VersionedDump.updatedAt.html","deprecated":false},{"id":"namespace_dumpfileurl","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"dumpFileUrl","file":"src/utils/shared/urls.ts","doc":"Returns the URL of the uploaded file of dump. The caller passes the session's media token (useAuth's mediaToken) as token, which goes in the query string since a media element can't send a header. The server needs it for a private dump's file.","url":"./src/utils/shared/urls.ts/~/dumpFileUrl.html","deprecated":false},{"id":"namespace_dumpthumbnailurl","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"dumpThumbnailUrl","file":"src/utils/shared/urls.ts","doc":"Returns the URL of the thumbnail of dump, with the media token as for dumpFileUrl. The server answers with the custom thumbnail if the dump has one, or else with one made from the file, a video still or a scaled-down image.","url":"./src/utils/shared/urls.ts/~/dumpThumbnailUrl.html","deprecated":false},{"id":"namespace_dumpwaveformurl","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"dumpWaveformUrl","file":"src/utils/shared/urls.ts","doc":"Returns the URL of the waveform of the audio file dump, which the server makes from the file, with the media token as for dumpFileUrl. The player draws it to seek on.","url":"./src/utils/shared/urls.ts/~/dumpWaveformUrl.html","deprecated":false},{"id":"namespace_feedapiurl","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"feedApiUrl","file":"src/utils/shared/urls.ts","doc":"Returns the URL of the feed's dumps, GET /api/dumps, every dump's or those of the category categorySlug; pageUrl adds the page to it. The index page loads it, and landingRequest names it to start it early.","url":"./src/utils/shared/urls.ts/~/feedApiUrl.html","deprecated":false},{"id":"namespace_normalizeurl","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"normalizeUrl","file":"src/utils/shared/urls.ts","doc":"Returns what a user typed as a link, trimmed, with https:// added when it has no http(s) scheme. The result is not checked to be a valid URL.","url":"./src/utils/shared/urls.ts/~/normalizeUrl.html","deprecated":false},{"id":"namespace_dumpurl","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"dumpUrl","file":"src/utils/shared/urls.ts","doc":"Returns the path of the page of dump, /@owner/dumps/<slug>, or of its editor (dumpPath). Its owner's name and its slug come with every dump the API sends.","url":"./src/utils/shared/urls.ts/~/dumpUrl.html","deprecated":false},{"id":"namespace_isat","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isAt","file":"src/utils/shared/urls.ts","doc":"Checks whether item, a dump or a playlist, is the one a page's /@username/…/slug names, the name in any case. A page that already shows it needn't fetch it again when its URL changes to its current path.","url":"./src/utils/shared/urls.ts/~/isAt.html","deprecated":false},{"id":"namespace_userapiurl","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"userApiUrl","file":"src/utils/shared/urls.ts","doc":"Returns the URL of /api/users/:key, or of what is under it, segments such as \"dumps\", slug, each encoded: every request about a user takes it from here. The key is user's id, or, when the caller has only the name a page's path gives, @ and that handle, which the API resolves as the page would, a former name or a remote user's included.","url":"./src/utils/shared/urls.ts/~/userApiUrl.html","deprecated":false},{"id":"namespace_playlisturl","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"playlistUrl","file":"src/utils/shared/urls.ts","doc":"Returns the path of the page of playlist, /@owner/playlists/<slug>, or of the page with its editor open (playlistPath).","url":"./src/utils/shared/urls.ts/~/playlistUrl.html","deprecated":false},{"id":"namespace_playlistimageurl","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"playlistImageUrl","file":"src/utils/shared/urls.ts","doc":"Returns the URL of the cover of playlist, versioned on updatedAt, which a new cover bumps. A private playlist's URL carries the media token, as for dumpFileUrl. A public one doesn't, so that its URL is the same for everyone. A playlist without isPublic counts as public.","url":"./src/utils/shared/urls.ts/~/playlistImageUrl.html","deprecated":false},{"id":"namespace_isapiimageurl","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isApiImageUrl","file":"src/utils/shared/urls.ts","doc":"Checks whether url is an image the API serves, its own or one it proxies, which all take ?w= and answer a scaled-down copy. Another site's image, loaded from its own host, doesn't.","url":"./src/utils/shared/urls.ts/~/isApiImageUrl.html","deprecated":false},{"id":"namespace_imageprops","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"imageProps","file":"src/utils/shared/urls.ts","doc":"Returns what an <img> needs to load url, one of the API's images, no larger than it is shown: a srcset of the copies the server makes (shared/image.ts), from which the browser takes the narrowest that fills sizes on its screen, and a src for whatever reads only that. sizes is the width the image is laid out at, in CSS pixels, or a sizes attribute when that width follows the viewport's. Avatar, Thumbnail and the playlists' covers spread it on their image.","url":"./src/utils/shared/urls.ts/~/imageProps.html","deprecated":false},{"id":"namespace_isdumpvisited","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isDumpVisited","file":"src/utils/shared/visited.ts","doc":"Checks whether dump id was opened in this browser.","url":"./src/utils/shared/visited.ts/~/isDumpVisited.html","deprecated":false},{"id":"namespace_isplaylistvisited","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isPlaylistVisited","file":"src/utils/shared/visited.ts","doc":"Checks whether playlist id was opened in this browser.","url":"./src/utils/shared/visited.ts/~/isPlaylistVisited.html","deprecated":false},{"id":"namespace_markdumpvisited","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"markDumpVisited","file":"src/utils/shared/visited.ts","doc":"Records dump id as opened. Nothing re-renders, so a card already on screen keeps its dot until it renders again.","url":"./src/utils/shared/visited.ts/~/markDumpVisited.html","deprecated":false},{"id":"namespace_markplaylistvisited","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"markPlaylistVisited","file":"src/utils/shared/visited.ts","doc":"Records playlist id as opened, as markDumpVisited does a dump.","url":"./src/utils/shared/visited.ts/~/markPlaylistVisited.html","deprecated":false},{"id":"namespace_isrecent","kind":[{"char":"f","kind":"Function","title":"Function"}],"name":"isRecent","file":"src/utils/shared/visited.ts","doc":"Checks whether createdAt is less than 7 days old. Older items show no unread dot, since an old item not opened here isn't news.","url":"./src/utils/shared/visited.ts/~/isRecent.html","deprecated":false}]};
|
||
})() |