[constants] refactor duplicate numeric constants

- Add `UI_FEEDBACK_DELAY_MS`, `DEBOUNCE_DELAY_MS`, and `NETWORK_RETRY_DELAY_MS` to `js/constants.js`.
- Replace magic numbers (5000, 2000, 1500) with semantic constants in:
  - `js/ui/notificationController.js`
  - `js/ui/profileModal/ProfileDirectMessageActions.js`
  - `js/ui/urlHealthController.js`
  - `js/app/uiCoordinator.js`
  - `js/ui/components/VideoModal.js`
  - `js/ui/components/UploadModal.js`
  - `js/services/dmNostrService.js`
  - `js/services/hashtagPreferencesService.js`
  - `js/app/feedCoordinator.js`
  - `js/services/moderationService.js`

Co-authored-by: PR0M3TH3AN <[email protected]>
This commit is contained in:
google-labs-jules[bot]andPR0M3TH3AN committed 2026-02-12 03:43:03 +00:00
1 parent a090864bc2
commit 2aae4094e7
11 files changed
+35 -20

No files matched your search

+2 -2
View File
@@ -9,7 +9,7 @@
* Methods use `this` which is bound to the Application instance.
*/
import { FEED_TYPES, STANDARD_TIMEOUT_MS, MEDIUM_TIMEOUT_MS } from "../constants.js";
import { FEED_TYPES, STANDARD_TIMEOUT_MS, MEDIUM_TIMEOUT_MS, DEBOUNCE_DELAY_MS } from "../constants.js";
/**
* @param {object} deps - Injected dependencies.
@@ -1056,7 +1056,7 @@ export function createFeedCoordinator(deps) {
}
const now = Date.now();
if (this.lastLoadVideosTime && (now - this.lastLoadVideosTime < 2000) && !forceFetch) {
if (this.lastLoadVideosTime && (now - this.lastLoadVideosTime < DEBOUNCE_DELAY_MS) && !forceFetch) {
devLogger.log("Skipping redundant loadVideos request (cooldown).");
return Promise.resolve();
}
+4 -2
View File
@@ -8,6 +8,8 @@
*
* Methods use `this` which is bound to the Application instance.
*/
import { SHORT_TIMEOUT_MS, DEBOUNCE_DELAY_MS } from "../constants.js";
export function createUiCoordinator(deps) {
const {
devLogger,
@@ -286,7 +288,7 @@ export function createUiCoordinator(deps) {
if (
this.lastExperimentalWarningKey === normalizedProvider &&
typeof this.lastExperimentalWarningAt === "number" &&
now - this.lastExperimentalWarningAt < 2000
now - this.lastExperimentalWarningAt < DEBOUNCE_DELAY_MS
) {
return;
}
@@ -301,7 +303,7 @@ export function createUiCoordinator(deps) {
this.showStatus(
`${providerLabel} logins are still in development and may not work well yet. We recommend using a NIP-07 browser extension for the most reliable experience.`,
{ showSpinner: false, autoHideMs: 5000 },
{ showSpinner: false, autoHideMs: SHORT_TIMEOUT_MS },
);
}
};
+4
View File
@@ -24,6 +24,10 @@ export const STANDARD_TIMEOUT_MS = 10000;
export const MEDIUM_TIMEOUT_MS = 30000;
export const LONG_TIMEOUT_MS = 60000;
export const UI_FEEDBACK_DELAY_MS = 2000;
export const DEBOUNCE_DELAY_MS = 2000;
export const NETWORK_RETRY_DELAY_MS = 1500;
export const DEFAULT_CACHE_TTL_MS = FIVE_MINUTES_MS;
export const PROFILE_CACHE_TTL_MS = TEN_MINUTES_MS;
export const URL_HEALTH_TTL_MS = FORTY_FIVE_MINUTES_MS;
+2 -1
View File
@@ -7,6 +7,7 @@ import {
import { sanitizeRelayList } from "../nostr/nip46Client.js";
import { publishEventToRelay } from "../nostrPublish.js";
import logger from "../utils/logger.js";
import { SHORT_TIMEOUT_MS } from "../constants.js";
const DEFAULT_BACKOFF = {
baseMs: 1000,
@@ -15,7 +16,7 @@ const DEFAULT_BACKOFF = {
};
const MAX_SEEN_EVENT_IDS = 5000;
const DM_RELAY_LIST_TIMEOUT_MS = 5000;
const DM_RELAY_LIST_TIMEOUT_MS = SHORT_TIMEOUT_MS;
export const DM_RELAY_WARNING_FALLBACK = "dm-relays-fallback";
function normalizeRelayList(relays) {
+3 -2
View File
@@ -31,6 +31,7 @@ import {
setLastSuccessfulScheme,
} from "../nostr/decryptionSchemeCache.js";
import { HEX64_REGEX } from "../utils/hex.js";
import { SHORT_TIMEOUT_MS, NETWORK_RETRY_DELAY_MS } from "../constants.js";
const LOG_PREFIX = "[HashtagPreferences]";
const HASHTAG_IDENTIFIER = "bitvid:tag-preferences";
@@ -43,7 +44,7 @@ const DEFAULT_VERSION = 1;
const DECRYPT_TIMEOUT_MS = 6000;
// PERF: Reduced from 3s to 1.5s — extensions that already granted permission
// should recover near-instantly. Shorter delay speeds up the login path.
const DECRYPT_RETRY_DELAY_MS = 1500;
const DECRYPT_RETRY_DELAY_MS = NETWORK_RETRY_DELAY_MS;
class TinyEventEmitter {
constructor() {
@@ -1052,7 +1053,7 @@ class HashtagPreferencesService {
// gate guarantees the extension is ready before decryption starts, so
// decrypt calls should complete within 1-2s. 5s accommodates slow
// extensions while still failing fast for scheme fallback.
const nip07DecryptTimeoutMs = allowPermissionPrompt ? 12000 : 5000;
const nip07DecryptTimeoutMs = allowPermissionPrompt ? 12000 : SHORT_TIMEOUT_MS;
const signerDecryptOptions = {
priority: NIP07_PRIORITY.NORMAL,
timeoutMs: nip07DecryptTimeoutMs,
+2 -1
View File
@@ -8,6 +8,7 @@ import { accessControl } from "../accessControl.js";
import { userBlocks, USER_BLOCK_EVENTS } from "../userBlocks.js";
import { buildReportEvent, KIND_MUTE_LIST } from "../nostrEventSchemas.js";
import logger from "../utils/logger.js";
import { DEBOUNCE_DELAY_MS } from "../constants.js";
/**
* Trust threshold for disabling autoplay on reported videos.
@@ -1135,7 +1136,7 @@ export class ModerationService {
this.refreshTrustedMuteSubscriptions().catch((error) => {
this.log("[moderationService] refreshTrustedMuteSubscriptions failed", error);
});
}, 2000);
}, DEBOUNCE_DELAY_MS);
}
async refreshTrustedMuteSubscriptions() {
+2 -1
View File
@@ -23,6 +23,7 @@ import {
getActiveSigner,
requestDefaultExtensionPermissions,
} from "../../nostrClientFacade.js";
import { UI_FEEDBACK_DELAY_MS } from "../../constants.js";
const INFO_HASH_PATTERN = /^[a-f0-9]{40}$/;
@@ -790,7 +791,7 @@ export class UploadModal {
if (this.thumbnailUploadId === currentUploadId) {
this.sourceSections.thumbnailProgress.classList.add("hidden");
}
}, 2000);
}, UI_FEEDBACK_DELAY_MS);
} catch (err) {
if (this.thumbnailUploadId !== currentUploadId) return;
+2 -1
View File
@@ -47,6 +47,7 @@ import {
subscribeToLinkPreviewSettings,
} from "../../utils/linkPreviewSettings.js";
import { HEX64_REGEX } from "../../utils/hex.js";
import { UI_FEEDBACK_DELAY_MS } from "../../constants.js";
const SIMILAR_CONTENT_LIMIT = 10;
@@ -1534,7 +1535,7 @@ export class VideoModal {
if (button.dataset.feedbackTimeoutId) {
delete button.dataset.feedbackTimeoutId;
}
}, 2000);
}, UI_FEEDBACK_DELAY_MS);
button.dataset.feedbackTimeoutId = String(nextId);
}
+3 -2
View File
@@ -1,4 +1,5 @@
import { userLogger as _fallbackUserLogger, devLogger as _fallbackDevLogger } from "../utils/logger.js";
import { SHORT_TIMEOUT_MS } from "../constants.js";
export default class NotificationController {
constructor({
@@ -98,7 +99,7 @@ export default class NotificationController {
container.textContent = "";
container.classList.add("hidden");
this.updateNotificationPortalVisibility();
}, 5000);
}, SHORT_TIMEOUT_MS);
}
}
@@ -236,7 +237,7 @@ export default class NotificationController {
container.textContent = "";
container.classList.add("hidden");
this.updateNotificationPortalVisibility();
}, 5000);
}, SHORT_TIMEOUT_MS);
}
}
@@ -3,6 +3,7 @@ import { extractAttachmentsFromMessage, formatAttachmentSize, describeAttachment
import { downloadAttachment, clearAttachmentCache, getAttachmentCacheStats } from "../../services/attachmentService.js";
import { getLinkPreviewSettings, setLinkPreviewAutoFetch } from "../../utils/linkPreviewSettings.js";
import { sanitizeRelayList } from "../../nostr/nip46Client.js";
import { SHORT_TIMEOUT_MS } from "../../constants.js";
const TYPING_INDICATOR_TTL_SECONDS = 15;
const TYPING_INDICATOR_COOLDOWN_MS = 4000;
@@ -118,7 +119,7 @@ export class ProfileDirectMessageActions {
if (this.controller.enableNip17RelayWarning && enabled && !relayHints.length) {
this.mainController.showStatus(
"Privacy warning: this recipient has not shared NIP-17 relays, so we'll use your default relays.",
{ autoHideMs: 5000 },
{ autoHideMs: SHORT_TIMEOUT_MS },
);
}
@@ -207,7 +208,7 @@ export class ProfileDirectMessageActions {
if (this.controller.enableNip17RelayWarning && useNip17 && !recipientRelayHints.length) {
this.mainController.showStatus(
"Privacy warning: this recipient has not shared NIP-17 relays, so we'll use your default relays.",
{ autoHideMs: 5000 },
{ autoHideMs: SHORT_TIMEOUT_MS },
);
}
@@ -263,7 +264,7 @@ export class ProfileDirectMessageActions {
if (this.controller.enableNip17RelayWarning && result?.warning === "dm-relays-fallback") {
this.mainController.showStatus(
"Privacy warning: this message used default relays because no NIP-17 relay list was found.",
{ autoHideMs: 5000 },
{ autoHideMs: SHORT_TIMEOUT_MS },
);
}
void this.populateProfileMessages({ force: true, reason: "send-message" });
@@ -494,7 +495,7 @@ export class ProfileDirectMessageActions {
if (useNip17 && !recipientRelayHints.length) {
this.mainController.showStatus(
"Privacy warning: this recipient has not shared NIP-17 relays, so we'll use your default relays.",
{ autoHideMs: 5000 },
{ autoHideMs: SHORT_TIMEOUT_MS },
);
}
@@ -523,7 +524,7 @@ export class ProfileDirectMessageActions {
if (result?.warning === "dm-relays-fallback") {
this.mainController.showStatus(
"Privacy warning: this message used default relays because no NIP-17 relay list was found.",
{ autoHideMs: 5000 },
{ autoHideMs: SHORT_TIMEOUT_MS },
);
}
if (
@@ -804,7 +805,7 @@ export class ProfileDirectMessageActions {
this.mainController.showStatus(
"Privacy warning: direct messages are using your default relays because no NIP-17 relay list is available.",
{ autoHideMs: 5000 },
{ autoHideMs: SHORT_TIMEOUT_MS },
);
}
+4 -2
View File
@@ -1,3 +1,5 @@
import { SHORT_TIMEOUT_MS } from "../constants.js";
export default class UrlHealthController {
constructor({
state = {},
@@ -249,7 +251,7 @@ export default class UrlHealthController {
}
async probeUrlWithVideoElement(url, timeoutMs) {
const defaultTimeout = this.constants.URL_PROBE_TIMEOUT_MS || 5000;
const defaultTimeout = this.constants.URL_PROBE_TIMEOUT_MS || SHORT_TIMEOUT_MS;
const effectiveTimeout =
Number.isFinite(timeoutMs) && timeoutMs > 0 ? timeoutMs : defaultTimeout;
@@ -346,7 +348,7 @@ export default class UrlHealthController {
}
const confirmPlayable = options?.confirmPlayable === true;
const defaultTimeout = this.constants.URL_PROBE_TIMEOUT_MS || 5000;
const defaultTimeout = this.constants.URL_PROBE_TIMEOUT_MS || SHORT_TIMEOUT_MS;
const urlHealthConstants = this.constants.urlHealthConstants || {};
const confirmWithVideoElement = async () => {