Files
bitvid/js/config.js
T
thePR0M3TH3AN 88c906fd34 Add BitLogin as the primary sign-in method (gated, unstable)
The login modal now shows <bitlogin-auth> -- a portable Nostr identity
behind a login name and password -- as the default sign-in path,
styled with bitvid's own brand tokens (accent-strong, surfaces, radii).
The existing NIP-07 extension, nsec, and NIP-46 remote-signer options
still work exactly as before, just collapsed under a new "Other login
options" fold instead of a flat "Available methods" grid; nip07 no
longer carries the stale "Recommended" eyebrow now that BitLogin has
that role.

BitLogin isn't a single button-click-then-await-a-promise flow like
the other providers -- it's a whole multi-screen sign-in/create/recover
UI -- so it gets a permanent, statically-declared widget in
components/login-modal.html (js/ui/bitloginModalIntegration.js relocates
it, never destroys and recreates it, since removal tears down its crypto
Web Worker) instead of a grid button. It still goes through the exact
same session-establishment path as every other signer: a new "bitlogin"
provider (js/services/authProviders/bitlogin.js) lets AuthService
resolve and activate it via the normal requestLogin -> handleAuthLogin
path, while providersForModal excludes it from the grid so it isn't
rendered twice.

Two things this needed beyond the wiring itself:
- js/app.js is one line from its lint/file-size ceiling, so the only
  change there is renaming an import binding (providers -> providersForModal),
  a net-zero line change. The actual widget/event wiring lives in a new,
  unconstrained module instead.
- The login modal's HTML (including the permanent widget element) loads
  asynchronously after bootstrap runs, so wireBitloginLogin() waits via
  MutationObserver rather than assuming a specific call order.

Vendored via scripts/build-bitlogin-widget.mjs (mirrors the existing
Bitcoin Connect/Blossom vendor steps): BitLogin isn't published to npm,
so the widget build is copied verbatim from the sibling ../bitlogin
checkout into committed vendor/bitlogin/, then lazy-imported (like
Bitcoin Connect) so its ~350KB never weighs on visitors who never open
the login modal.

Gated behind FEATURE_BITLOGIN (config/instance-config.js), default on
for this unstable-branch experiment per AGENTS.md §1 -- reset to false
before this reaches main until verified end-to-end against production
relays.

Verified: npm run lint (clean), the full auth/login test suite (43/43,
including new coverage for the provider + adapter), and a manual
Chrome pass against the built dist/ -- widget renders themed correctly,
"Other login options" still shows the original four methods unchanged.
2026-07-21 20:56:01 -04:00

187 lines
5.7 KiB
JavaScript

// js/config.js
import { userLogger } from "./utils/logger.js";
import {
IS_DEV_MODE,
IS_VERBOSE_DEV_MODE,
IS_LOCKDOWN_MODE,
LOCKDOWN_TITLE,
LOCKDOWN_MESSAGE,
ADMIN_SUPER_NPUB,
ADMIN_DM_IMAGE_URL,
BITVID_WEBSITE_URL,
BLOG_URL,
COMMUNITY_URL,
NOSTR_URL,
GITHUB_URL,
BETA_URL,
DNS_URL,
TIP_JAR_URL,
MAX_WALLET_DEFAULT_ZAP,
PLATFORM_FEE_PERCENT,
PLATFORM_LUD16_OVERRIDE,
DEFAULT_RELAY_URLS_OVERRIDE,
ADMIN_WHITELIST_MODE_STORAGE_KEY,
DEFAULT_WHITELIST_MODE_ENABLED,
ALLOW_NSFW_CONTENT,
FEATURE_NIP71_INGEST,
FEATURE_AUDIO_INGEST,
FEATURE_BITCOIN_CONNECT,
FEATURE_BITLOGIN,
FEATURE_BLOSSOM_STORAGE,
FEATURE_BLOSSOM_TORRENT_METADATA,
CARD_LIVENESS_POLICY,
LIVENESS_PROBE_PREFETCH_MARGIN,
DEFAULT_TRUST_SEED_NPUBS,
DEFAULT_BLUR_THRESHOLD,
DEFAULT_AUTOPLAY_BLOCK_THRESHOLD,
DEFAULT_TRUSTED_MUTE_HIDE_THRESHOLD,
DEFAULT_TRUSTED_SPAM_HIDE_THRESHOLD,
WATCH_HISTORY_KIND,
WATCH_HISTORY_LIST_IDENTIFIER,
WATCH_HISTORY_MAX_ITEMS,
WATCH_HISTORY_BATCH_RESOLVE,
WATCH_HISTORY_BATCH_PAGE_SIZE,
WATCH_HISTORY_PAYLOAD_MAX_BYTES,
WATCH_HISTORY_FETCH_EVENT_LIMIT,
WATCH_HISTORY_CACHE_TTL_MS,
VIEW_COUNT_DEDUPE_WINDOW_SECONDS,
VIEW_COUNT_BACKFILL_MAX_DAYS,
VIEW_COUNT_CACHE_TTL_MS,
ENSURE_PRESENCE_REBROADCAST_COOLDOWN_SECONDS,
DEFAULT_PLAYBACK_SOURCE,
DEFAULT_PLAYBACK_START_TIMEOUT,
ENABLE_NIP17_RELAY_WARNING,
} from "../config/instance-config.js";
export const WATCH_HISTORY_VERSION_TAG_VALUE = "2";
const runtimeScope = typeof globalThis === "undefined" ? null : globalThis;
const parseBooleanOverride = (value) => {
if (typeof value === "boolean") {
return value;
}
if (typeof value === "string") {
const normalized = value.trim().toLowerCase();
if (normalized === "true") {
return true;
}
if (normalized === "false") {
return false;
}
}
return null;
};
const devModeOverride = parseBooleanOverride(
runtimeScope?.__BITVID_DEV_MODE_OVERRIDE__
);
const verboseDevModeOverride = parseBooleanOverride(
runtimeScope?.__BITVID_VERBOSE_DEV_MODE_OVERRIDE__
);
export const isDevMode =
devModeOverride === null ? Boolean(IS_DEV_MODE) : devModeOverride;
export { IS_DEV_MODE };
export const isVerboseDevMode =
verboseDevModeOverride === null
? Boolean(IS_VERBOSE_DEV_MODE)
: verboseDevModeOverride;
export { IS_VERBOSE_DEV_MODE };
export const isLockdownMode = Boolean(IS_LOCKDOWN_MODE);
export { IS_LOCKDOWN_MODE };
export { LOCKDOWN_TITLE, LOCKDOWN_MESSAGE };
if (typeof window !== "undefined") {
window.__BITVID_DEV_MODE__ = isDevMode;
window.__BITVID_VERBOSE_DEV_MODE__ = isVerboseDevMode;
window.__BITVID_LOCKDOWN_MODE__ = isLockdownMode;
}
// -----------------------------------------------------------------------------
// Admin governance — production defaults rely on remote Nostr lists
// -----------------------------------------------------------------------------
export const ADMIN_LIST_MODE = "nostr";
export { ADMIN_SUPER_NPUB };
export { ADMIN_DM_IMAGE_URL };
export { BITVID_WEBSITE_URL };
export { BLOG_URL };
export { COMMUNITY_URL };
export { NOSTR_URL };
export { GITHUB_URL };
export { BETA_URL };
export { DNS_URL };
export { TIP_JAR_URL };
export { MAX_WALLET_DEFAULT_ZAP };
export { PLATFORM_FEE_PERCENT };
export { PLATFORM_LUD16_OVERRIDE };
export { DEFAULT_RELAY_URLS_OVERRIDE };
export const ADMIN_EDITORS_NPUBS = []; // Default moderators (optional)
export const ADMIN_LIST_NAMESPACE = "bitvid:admin"; // Reserved for Nostr lists
export const ADMIN_COMMUNITY_BLACKLIST_SOURCES = "community:blacklist:sources";
export const ADMIN_COMMUNITY_BLACKLIST_PREFIX = "community:blacklist";
export { ALLOW_NSFW_CONTENT };
export { FEATURE_NIP71_INGEST };
export { FEATURE_AUDIO_INGEST };
export { FEATURE_BITCOIN_CONNECT };
export { FEATURE_BITLOGIN };
export { FEATURE_BLOSSOM_STORAGE };
export { FEATURE_BLOSSOM_TORRENT_METADATA };
export { CARD_LIVENESS_POLICY };
export { LIVENESS_PROBE_PREFETCH_MARGIN };
export { DEFAULT_TRUST_SEED_NPUBS };
export { DEFAULT_BLUR_THRESHOLD };
export { DEFAULT_AUTOPLAY_BLOCK_THRESHOLD };
export { DEFAULT_TRUSTED_MUTE_HIDE_THRESHOLD };
export { DEFAULT_TRUSTED_SPAM_HIDE_THRESHOLD };
const WHITELIST_MODE_KEY = ADMIN_WHITELIST_MODE_STORAGE_KEY;
const DEFAULT_WHITELIST_ENABLED = DEFAULT_WHITELIST_MODE_ENABLED;
export function getWhitelistMode() {
try {
const raw = localStorage.getItem(WHITELIST_MODE_KEY);
if (raw === null) {
return DEFAULT_WHITELIST_ENABLED;
}
return raw === "true";
} catch (error) {
userLogger.warn("Failed to read whitelist mode from storage:", error);
return DEFAULT_WHITELIST_ENABLED;
}
}
export function setWhitelistMode(enabled) {
try {
localStorage.setItem(WHITELIST_MODE_KEY, enabled ? "true" : "false");
} catch (error) {
userLogger.warn("Failed to persist whitelist mode to storage:", error);
}
}
export { ADMIN_WHITELIST_MODE_STORAGE_KEY };
// -----------------------------------------------------------------------------
// Watch history — roadmap defaults balance retention with relay load
// -----------------------------------------------------------------------------
export { WATCH_HISTORY_KIND };
export { WATCH_HISTORY_LIST_IDENTIFIER };
export { WATCH_HISTORY_MAX_ITEMS };
export { WATCH_HISTORY_BATCH_RESOLVE };
export { WATCH_HISTORY_BATCH_PAGE_SIZE };
export { WATCH_HISTORY_PAYLOAD_MAX_BYTES };
export { WATCH_HISTORY_FETCH_EVENT_LIMIT };
export { WATCH_HISTORY_CACHE_TTL_MS };
export { VIEW_COUNT_DEDUPE_WINDOW_SECONDS };
export { VIEW_COUNT_BACKFILL_MAX_DAYS };
export { VIEW_COUNT_CACHE_TTL_MS };
export { ENSURE_PRESENCE_REBROADCAST_COOLDOWN_SECONDS };
export { DEFAULT_PLAYBACK_SOURCE };
export { DEFAULT_PLAYBACK_START_TIMEOUT };
export { ENABLE_NIP17_RELAY_WARNING };