mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-11-03 19:35:28 +00:00
refactor(watch-history): extract actor helpers from watchHistoryService (4/10)
File-size decomposition (no behavior change). Move getLoggedInActorKey, getSessionActorKey, and ensureWatchHistoryExtensionPermissions (which depend only on imported singletons, not module state) into js/watchHistoryActorHelpers.js, and drop the now-unused getActiveSigner/requestDefaultExtensionPermissions/getApplication imports from the service. watchHistoryService.js: 1491 -> 1388 lines (below its original 1395 baseline; re-recorded to 1386 to lock the reduction). Build + full unit suite green. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
b068854c94
commit
37a675392f
3 files changed
+126
-110
No files matched your search
@@ -0,0 +1,119 @@
|
||||
// js/watchHistoryActorHelpers.js
|
||||
//
|
||||
// Actor-key resolution + extension-permission helpers extracted from
|
||||
// watchHistoryService.js to keep that module under the file-size budget. These
|
||||
// depend only on imported singletons (no watchHistoryService module state), so
|
||||
// they move cleanly. No behavior change.
|
||||
|
||||
import {
|
||||
getActiveSigner,
|
||||
nostrClient,
|
||||
requestDefaultExtensionPermissions,
|
||||
} from "./nostrClientFacade.js";
|
||||
import { normalizeActorKey } from "./nostr/watchHistory.js";
|
||||
import { getApplication } from "./applicationContext.js";
|
||||
import { devLogger, userLogger } from "./utils/logger.js";
|
||||
|
||||
export function getLoggedInActorKey() {
|
||||
const direct = normalizeActorKey(nostrClient?.pubkey);
|
||||
if (direct) {
|
||||
return direct;
|
||||
}
|
||||
|
||||
if (typeof window !== "undefined") {
|
||||
const appCandidate =
|
||||
getApplication() || null;
|
||||
if (appCandidate && typeof appCandidate === "object") {
|
||||
if (typeof appCandidate.normalizeHexPubkey === "function") {
|
||||
try {
|
||||
const normalized = appCandidate.normalizeHexPubkey(
|
||||
appCandidate.pubkey
|
||||
);
|
||||
if (normalized) {
|
||||
return normalizeActorKey(normalized);
|
||||
}
|
||||
} catch (error) {
|
||||
devLogger.warn(
|
||||
"[watchHistoryService] Failed to normalize app login pubkey:",
|
||||
error
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof appCandidate.pubkey === "string" && appCandidate.pubkey) {
|
||||
const fallback = normalizeActorKey(appCandidate.pubkey);
|
||||
if (fallback) {
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
export function getSessionActorKey() {
|
||||
const logged = getLoggedInActorKey();
|
||||
if (logged) {
|
||||
return "";
|
||||
}
|
||||
return normalizeActorKey(nostrClient?.sessionActor?.pubkey);
|
||||
}
|
||||
|
||||
export async function ensureWatchHistoryExtensionPermissions(actorKey, options = {}) {
|
||||
const normalizedActor = normalizeActorKey(actorKey);
|
||||
if (!normalizedActor) {
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
const loggedActor = normalizeActorKey(nostrClient?.pubkey);
|
||||
if (!loggedActor || loggedActor !== normalizedActor) {
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
const allowPermissionPrompt = options?.allowPermissionPrompt !== false;
|
||||
|
||||
// FIX: Always attempt to resolve the signer regardless of allowPermissionPrompt.
|
||||
// ensureActiveSignerForPubkey does not prompt the user — it only resolves an
|
||||
// already-injected extension or returns the existing signer.
|
||||
let signer = getActiveSigner();
|
||||
if (
|
||||
!signer && typeof nostrClient?.ensureActiveSignerForPubkey === "function"
|
||||
) {
|
||||
signer = await nostrClient.ensureActiveSignerForPubkey(normalizedActor);
|
||||
}
|
||||
|
||||
const canSign = typeof signer?.canSign === "function"
|
||||
? signer.canSign()
|
||||
: typeof signer?.signEvent === "function";
|
||||
// FIX: NIP-07 adapters use type "nip07", not "extension". Both types
|
||||
// represent browser extension signers that need permission pre-granting.
|
||||
if (!canSign || (signer?.type !== "extension" && signer?.type !== "nip07")) {
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
if (!allowPermissionPrompt) {
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
const permissionResult = await requestDefaultExtensionPermissions();
|
||||
if (permissionResult.ok) {
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
const message =
|
||||
"Approve your NIP-07 extension to sync watch history.";
|
||||
const error = new Error(message);
|
||||
error.code = "watch-history-extension-permission-denied";
|
||||
error.cause = permissionResult.error;
|
||||
|
||||
userLogger.warn(
|
||||
"[watchHistoryService] Extension denied decrypt permission required for watch history.",
|
||||
{
|
||||
actor: normalizeActorKey(actorKey) || null,
|
||||
error: permissionResult.error,
|
||||
},
|
||||
);
|
||||
|
||||
return { ok: false, error };
|
||||
}
|
||||
+6
-109
@@ -1,10 +1,6 @@
|
||||
// js/watchHistoryService.js
|
||||
|
||||
import {
|
||||
getActiveSigner,
|
||||
nostrClient,
|
||||
requestDefaultExtensionPermissions,
|
||||
} from "./nostrClientFacade.js";
|
||||
import { nostrClient } from "./nostrClientFacade.js";
|
||||
import {
|
||||
normalizePointerInput,
|
||||
pointerKey,
|
||||
@@ -14,9 +10,13 @@ import {
|
||||
WATCH_HISTORY_CACHE_TTL_MS,
|
||||
WATCH_HISTORY_MAX_ITEMS,
|
||||
} from "./config.js";
|
||||
import { getApplication } from "./applicationContext.js";
|
||||
import { devLogger, userLogger } from "./utils/logger.js";
|
||||
import { ONE_MINUTE_MS } from "./constants.js";
|
||||
import {
|
||||
getLoggedInActorKey,
|
||||
getSessionActorKey,
|
||||
ensureWatchHistoryExtensionPermissions,
|
||||
} from "./watchHistoryActorHelpers.js";
|
||||
|
||||
const LOCAL_STORAGE_QUEUE_KEY = "bitvid:watch-history:queue:v1";
|
||||
const SESSION_STORAGE_VERSION = 1;
|
||||
@@ -38,109 +38,6 @@ const state = {
|
||||
chunkBackfills: new Set(),
|
||||
};
|
||||
|
||||
function getLoggedInActorKey() {
|
||||
const direct = normalizeActorKey(nostrClient?.pubkey);
|
||||
if (direct) {
|
||||
return direct;
|
||||
}
|
||||
|
||||
if (typeof window !== "undefined") {
|
||||
const appCandidate =
|
||||
getApplication() || null;
|
||||
if (appCandidate && typeof appCandidate === "object") {
|
||||
if (typeof appCandidate.normalizeHexPubkey === "function") {
|
||||
try {
|
||||
const normalized = appCandidate.normalizeHexPubkey(
|
||||
appCandidate.pubkey
|
||||
);
|
||||
if (normalized) {
|
||||
return normalizeActorKey(normalized);
|
||||
}
|
||||
} catch (error) {
|
||||
devLogger.warn(
|
||||
"[watchHistoryService] Failed to normalize app login pubkey:",
|
||||
error
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof appCandidate.pubkey === "string" && appCandidate.pubkey) {
|
||||
const fallback = normalizeActorKey(appCandidate.pubkey);
|
||||
if (fallback) {
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
function getSessionActorKey() {
|
||||
const logged = getLoggedInActorKey();
|
||||
if (logged) {
|
||||
return "";
|
||||
}
|
||||
return normalizeActorKey(nostrClient?.sessionActor?.pubkey);
|
||||
}
|
||||
|
||||
async function ensureWatchHistoryExtensionPermissions(actorKey, options = {}) {
|
||||
const normalizedActor = normalizeActorKey(actorKey);
|
||||
if (!normalizedActor) {
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
const loggedActor = normalizeActorKey(nostrClient?.pubkey);
|
||||
if (!loggedActor || loggedActor !== normalizedActor) {
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
const allowPermissionPrompt = options?.allowPermissionPrompt !== false;
|
||||
|
||||
// FIX: Always attempt to resolve the signer regardless of allowPermissionPrompt.
|
||||
// ensureActiveSignerForPubkey does not prompt the user — it only resolves an
|
||||
// already-injected extension or returns the existing signer.
|
||||
let signer = getActiveSigner();
|
||||
if (
|
||||
!signer && typeof nostrClient?.ensureActiveSignerForPubkey === "function"
|
||||
) {
|
||||
signer = await nostrClient.ensureActiveSignerForPubkey(normalizedActor);
|
||||
}
|
||||
|
||||
const canSign = typeof signer?.canSign === "function"
|
||||
? signer.canSign()
|
||||
: typeof signer?.signEvent === "function";
|
||||
// FIX: NIP-07 adapters use type "nip07", not "extension". Both types
|
||||
// represent browser extension signers that need permission pre-granting.
|
||||
if (!canSign || (signer?.type !== "extension" && signer?.type !== "nip07")) {
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
if (!allowPermissionPrompt) {
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
const permissionResult = await requestDefaultExtensionPermissions();
|
||||
if (permissionResult.ok) {
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
const message =
|
||||
"Approve your NIP-07 extension to sync watch history.";
|
||||
const error = new Error(message);
|
||||
error.code = "watch-history-extension-permission-denied";
|
||||
error.cause = permissionResult.error;
|
||||
|
||||
userLogger.warn(
|
||||
"[watchHistoryService] Extension denied decrypt permission required for watch history.",
|
||||
{
|
||||
actor: normalizeActorKey(actorKey) || null,
|
||||
error: permissionResult.error,
|
||||
},
|
||||
);
|
||||
|
||||
return { ok: false, error };
|
||||
}
|
||||
|
||||
function resolveEffectiveActorKey(actorInput) {
|
||||
const supplied =
|
||||
|
||||
@@ -52,7 +52,7 @@ const GRANDFATHERED = {
|
||||
"js/services/hashtagPreferencesService.js": 1434,
|
||||
"js/nostr/publishHelpers.js": 1415,
|
||||
"js/index.js": 1412,
|
||||
"js/watchHistoryService.js": 1395,
|
||||
"js/watchHistoryService.js": 1386,
|
||||
"js/app/playbackCoordinator.js": 1376,
|
||||
"js/feedEngine/stages.js": 1370,
|
||||
"js/ui/views/VideoListView.js": 1359,
|
||||
|
||||
Reference in new issue
Block a user