lint fix wip
This commit is contained in:
parent
899c20631a
commit
f471fa3d31
@ -36,7 +36,7 @@ export function ArticleEditor({ onPublishSuccess, onCancel, seriesOptions, onSel
|
|||||||
const submit = buildSubmitHandler({
|
const submit = buildSubmitHandler({
|
||||||
publishArticle,
|
publishArticle,
|
||||||
draft,
|
draft,
|
||||||
onPublishSuccess,
|
...(onPublishSuccess ? { onPublishSuccess } : {}),
|
||||||
connect,
|
connect,
|
||||||
connected,
|
connected,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -123,7 +123,7 @@ export function ConnectButton(): React.ReactElement {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (mode === 'connected') {
|
if (mode === 'connected') {
|
||||||
return <ConnectedState pubkey={pubkey} profile={profile} loading={loading} disconnect={disconnect} />
|
return <ConnectedState pubkey={requirePubkey(pubkey)} profile={profile} loading={loading} disconnect={disconnect} />
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode === 'unlock_required') {
|
if (mode === 'unlock_required') {
|
||||||
@ -146,3 +146,12 @@ export function ConnectButton(): React.ReactElement {
|
|||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function requirePubkey(pubkey: string | null): string {
|
||||||
|
if (!pubkey) {
|
||||||
|
const error = new Error('Invariant violation: pubkey is required when ConnectButton mode is "connected"')
|
||||||
|
console.error(error.message, { pubkey })
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
return pubkey
|
||||||
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import type { ReviewFormProps } from './reviewForms/reviewFormTypes'
|
|||||||
|
|
||||||
export function ReviewForm({ article, onSuccess, onCancel }: ReviewFormProps): React.ReactElement {
|
export function ReviewForm({ article, onSuccess, onCancel }: ReviewFormProps): React.ReactElement {
|
||||||
const { pubkey, connect } = useNostrAuth()
|
const { pubkey, connect } = useNostrAuth()
|
||||||
const ctrl = useReviewFormController({ article, pubkey, onSuccess })
|
const ctrl = useReviewFormController({ article, pubkey, ...(onSuccess ? { onSuccess } : {}) })
|
||||||
|
|
||||||
if (!pubkey) {
|
if (!pubkey) {
|
||||||
return (
|
return (
|
||||||
@ -20,5 +20,5 @@ export function ReviewForm({ article, onSuccess, onCancel }: ReviewFormProps): R
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return <ReviewFormView ctrl={ctrl} onCancel={onCancel} />
|
return <ReviewFormView ctrl={ctrl} {...(onCancel ? { onCancel } : {})} />
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import type { ReviewTipFormProps } from './reviewForms/reviewFormTypes'
|
|||||||
|
|
||||||
export function ReviewTipForm({ review, article, onSuccess, onCancel }: ReviewTipFormProps): React.ReactElement {
|
export function ReviewTipForm({ review, article, onSuccess, onCancel }: ReviewTipFormProps): React.ReactElement {
|
||||||
const { pubkey, connect } = useNostrAuth()
|
const { pubkey, connect } = useNostrAuth()
|
||||||
const ctrl = useReviewTipFormController({ review, article, pubkey, onSuccess })
|
const ctrl = useReviewTipFormController({ review, article, pubkey, ...(onSuccess ? { onSuccess } : {}) })
|
||||||
|
|
||||||
if (!pubkey) {
|
if (!pubkey) {
|
||||||
return (
|
return (
|
||||||
@ -19,5 +19,5 @@ export function ReviewTipForm({ review, article, onSuccess, onCancel }: ReviewTi
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return <ReviewTipFormView ctrl={ctrl} onCancel={onCancel} />
|
return <ReviewTipFormView ctrl={ctrl} {...(onCancel ? { onCancel } : {})} />
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,7 +37,7 @@ export function useReviewFormController(params: {
|
|||||||
setLoading,
|
setLoading,
|
||||||
setError,
|
setError,
|
||||||
reset: () => resetFields({ setContent, setTitle, setText }),
|
reset: () => resetFields({ setContent, setTitle, setText }),
|
||||||
onSuccess: params.onSuccess,
|
...(params.onSuccess ? { onSuccess: params.onSuccess } : {}),
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -67,7 +67,8 @@ function buildReviewSubmitHandler(params: {
|
|||||||
}): (e: React.FormEvent) => Promise<void> {
|
}): (e: React.FormEvent) => Promise<void> {
|
||||||
return async (e: React.FormEvent): Promise<void> => {
|
return async (e: React.FormEvent): Promise<void> => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
if (!params.pubkey) {
|
const pubkey = params.pubkey
|
||||||
|
if (!pubkey) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const contentError = validateRequiredContent(params.content)
|
const contentError = validateRequiredContent(params.content)
|
||||||
@ -75,7 +76,7 @@ function buildReviewSubmitHandler(params: {
|
|||||||
params.setError(contentError)
|
params.setError(contentError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
await submitReview(params)
|
await submitReview({ ...params, pubkey })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import { articlePublisher } from '@/lib/articlePublisher'
|
|||||||
import { nostrService } from '@/lib/nostr'
|
import { nostrService } from '@/lib/nostr'
|
||||||
import type { ArticleDraft } from '@/lib/articlePublisher'
|
import type { ArticleDraft } from '@/lib/articlePublisher'
|
||||||
import type { RelayPublishStatus } from '@/lib/publishResult'
|
import type { RelayPublishStatus } from '@/lib/publishResult'
|
||||||
|
import type { PublishedArticle } from '@/lib/articlePublisherTypes'
|
||||||
|
|
||||||
interface UseArticlePublishingState {
|
interface UseArticlePublishingState {
|
||||||
loading: boolean
|
loading: boolean
|
||||||
@ -83,7 +84,7 @@ function buildPublishArticleHandler(params: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handlePublishResult(params: {
|
function handlePublishResult(params: {
|
||||||
result: { success: boolean; relayStatuses?: RelayPublishStatus[]; articleId: string | null; error?: string | undefined }
|
result: PublishedArticle
|
||||||
setSuccess: (success: boolean) => void
|
setSuccess: (success: boolean) => void
|
||||||
setRelayStatuses: (statuses: RelayPublishStatus[]) => void
|
setRelayStatuses: (statuses: RelayPublishStatus[]) => void
|
||||||
setError: (error: string | null) => void
|
setError: (error: string | null) => void
|
||||||
@ -91,7 +92,7 @@ function handlePublishResult(params: {
|
|||||||
if (params.result.success) {
|
if (params.result.success) {
|
||||||
params.setSuccess(true)
|
params.setSuccess(true)
|
||||||
params.setRelayStatuses(params.result.relayStatuses ?? [])
|
params.setRelayStatuses(params.result.relayStatuses ?? [])
|
||||||
return params.result.articleId
|
return params.result.articleId ? params.result.articleId : null
|
||||||
}
|
}
|
||||||
|
|
||||||
params.setError(params.result.error ?? 'Failed to publish article')
|
params.setError(params.result.error ?? 'Failed to publish article')
|
||||||
|
|||||||
@ -77,7 +77,13 @@ export class ArticlePublisher {
|
|||||||
return buildFailure('Presentation not found')
|
return buildFailure('Presentation not found')
|
||||||
}
|
}
|
||||||
|
|
||||||
return encryptAndPublish(draft, authorPubkey, validation.authorPrivateKeyForEncryption, validation.category, presentation.id)
|
return encryptAndPublish({
|
||||||
|
draft,
|
||||||
|
authorPubkey,
|
||||||
|
authorPrivateKeyForEncryption: validation.authorPrivateKeyForEncryption,
|
||||||
|
category: validation.category,
|
||||||
|
presentationId: presentation.id,
|
||||||
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error publishing article:', error)
|
console.error('Error publishing article:', error)
|
||||||
return buildFailure(error instanceof Error ? error.message : 'Unknown error')
|
return buildFailure(error instanceof Error ? error.message : 'Unknown error')
|
||||||
|
|||||||
@ -23,77 +23,78 @@ export function createMessageVerificationFilters(messageEventId: string, authorP
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface MessageVerificationContext {
|
||||||
|
messageEventId: string
|
||||||
|
articleId: string
|
||||||
|
recipientPubkey: string
|
||||||
|
authorPubkey: string
|
||||||
|
}
|
||||||
|
|
||||||
export function handleMessageVerificationEvent(
|
export function handleMessageVerificationEvent(
|
||||||
event: import('nostr-tools').Event,
|
event: import('nostr-tools').Event,
|
||||||
articleId: string,
|
ctx: MessageVerificationContext,
|
||||||
recipientPubkey: string,
|
|
||||||
authorPubkey: string,
|
|
||||||
finalize: (value: boolean) => void
|
finalize: (value: boolean) => void
|
||||||
): void {
|
): void {
|
||||||
console.warn('Private message verified on relay', {
|
console.warn('Private message verified on relay', {
|
||||||
messageEventId: event.id,
|
messageEventId: event.id,
|
||||||
articleId,
|
articleId: ctx.articleId,
|
||||||
recipientPubkey,
|
recipientPubkey: ctx.recipientPubkey,
|
||||||
authorPubkey,
|
authorPubkey: ctx.authorPubkey,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
})
|
})
|
||||||
finalize(true)
|
finalize(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setupMessageVerificationHandlers(
|
export function setupMessageVerificationHandlers(
|
||||||
sub: import('@/types/nostr-tools-extended').Subscription,
|
params: {
|
||||||
messageEventId: string,
|
sub: import('@/types/nostr-tools-extended').Subscription
|
||||||
articleId: string,
|
ctx: MessageVerificationContext
|
||||||
recipientPubkey: string,
|
finalize: (value: boolean) => void
|
||||||
authorPubkey: string,
|
|
||||||
finalize: (value: boolean) => void,
|
|
||||||
isResolved: () => boolean
|
isResolved: () => boolean
|
||||||
|
}
|
||||||
): void {
|
): void {
|
||||||
sub.on('event', (event: Event): void => {
|
params.sub.on('event', (event: Event): void => {
|
||||||
handleMessageVerificationEvent(event, articleId, recipientPubkey, authorPubkey, finalize)
|
handleMessageVerificationEvent(event, params.ctx, params.finalize)
|
||||||
})
|
})
|
||||||
|
|
||||||
sub.on('eose', (): void => {
|
params.sub.on('eose', (): void => {
|
||||||
console.warn('Private message not found on relay after EOSE', {
|
console.warn('Private message not found on relay after EOSE', {
|
||||||
messageEventId,
|
messageEventId: params.ctx.messageEventId,
|
||||||
articleId,
|
articleId: params.ctx.articleId,
|
||||||
recipientPubkey,
|
recipientPubkey: params.ctx.recipientPubkey,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
})
|
})
|
||||||
finalize(false)
|
params.finalize(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (!isResolved()) {
|
if (!params.isResolved()) {
|
||||||
console.warn('Timeout verifying private message on relay', {
|
console.warn('Timeout verifying private message on relay', {
|
||||||
messageEventId,
|
messageEventId: params.ctx.messageEventId,
|
||||||
articleId,
|
articleId: params.ctx.articleId,
|
||||||
recipientPubkey,
|
recipientPubkey: params.ctx.recipientPubkey,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
})
|
})
|
||||||
finalize(false)
|
params.finalize(false)
|
||||||
}
|
}
|
||||||
}, 5000)
|
}, 5000)
|
||||||
}
|
}
|
||||||
|
|
||||||
function createMessageVerificationSubscription(
|
function createMessageVerificationSubscription(
|
||||||
pool: import('nostr-tools').SimplePool,
|
params: { pool: import('nostr-tools').SimplePool; ctx: MessageVerificationContext }
|
||||||
messageEventId: string,
|
|
||||||
authorPubkey: string,
|
|
||||||
recipientPubkey: string,
|
|
||||||
articleId: string
|
|
||||||
): ReturnType<typeof createSubscription> {
|
): ReturnType<typeof createSubscription> {
|
||||||
const filters = createMessageVerificationFilters(messageEventId, authorPubkey, recipientPubkey, articleId)
|
const filters = createMessageVerificationFilters(
|
||||||
|
params.ctx.messageEventId,
|
||||||
|
params.ctx.authorPubkey,
|
||||||
|
params.ctx.recipientPubkey,
|
||||||
|
params.ctx.articleId
|
||||||
|
)
|
||||||
const relayUrl = getPrimaryRelaySync()
|
const relayUrl = getPrimaryRelaySync()
|
||||||
return createSubscription(pool, [relayUrl], filters)
|
return createSubscription(params.pool, [relayUrl], filters)
|
||||||
}
|
}
|
||||||
|
|
||||||
function createVerificationPromise(
|
function createVerificationPromise(
|
||||||
sub: import('@/types/nostr-tools-extended').Subscription,
|
params: { sub: import('@/types/nostr-tools-extended').Subscription; ctx: MessageVerificationContext }
|
||||||
messageEventId: string,
|
|
||||||
articleId: string,
|
|
||||||
recipientPubkey: string,
|
|
||||||
authorPubkey: string
|
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
return new Promise<boolean>((resolve) => {
|
return new Promise<boolean>((resolve) => {
|
||||||
let resolved = false
|
let resolved = false
|
||||||
@ -103,11 +104,11 @@ function createVerificationPromise(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
resolved = true
|
resolved = true
|
||||||
sub.unsub()
|
params.sub.unsub()
|
||||||
resolve(value)
|
resolve(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
setupMessageVerificationHandlers(sub, messageEventId, articleId, recipientPubkey, authorPubkey, finalize, () => resolved)
|
setupMessageVerificationHandlers({ sub: params.sub, ctx: params.ctx, finalize, isResolved: () => resolved })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,15 +129,9 @@ export function verifyPrivateMessagePublished(
|
|||||||
return Promise.resolve(false)
|
return Promise.resolve(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
const sub = createMessageVerificationSubscription(
|
const ctx: MessageVerificationContext = { messageEventId, articleId, recipientPubkey, authorPubkey }
|
||||||
pool,
|
const sub = createMessageVerificationSubscription({ pool, ctx })
|
||||||
messageEventId,
|
return createVerificationPromise({ sub, ctx })
|
||||||
authorPubkey,
|
|
||||||
recipientPubkey,
|
|
||||||
articleId
|
|
||||||
)
|
|
||||||
|
|
||||||
return createVerificationPromise(sub, messageEventId, articleId, recipientPubkey, authorPubkey)
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error verifying private message', {
|
console.error('Error verifying private message', {
|
||||||
messageEventId,
|
messageEventId,
|
||||||
|
|||||||
@ -77,16 +77,21 @@ async function buildParsedArticleFromDraft(
|
|||||||
return { article, hash, version, index }
|
return { article, hash, version, index }
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function publishPreview(
|
interface PublishPreviewParams {
|
||||||
draft: ArticleDraft,
|
draft: ArticleDraft
|
||||||
invoice: AlbyInvoice,
|
invoice: AlbyInvoice
|
||||||
authorPubkey: string,
|
authorPubkey: string
|
||||||
presentationId: string,
|
presentationId: string
|
||||||
extraTags?: string[][],
|
extraTags?: string[][]
|
||||||
encryptedContent?: string,
|
encryptedContent?: string
|
||||||
encryptedKey?: string,
|
encryptedKey?: string
|
||||||
returnStatus?: boolean
|
returnStatus?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function publishPreview(
|
||||||
|
params: PublishPreviewParams
|
||||||
): Promise<import('nostr-tools').Event | null | PublishResult> {
|
): Promise<import('nostr-tools').Event | null | PublishResult> {
|
||||||
|
const { draft, invoice, authorPubkey, presentationId, extraTags, encryptedContent, encryptedKey, returnStatus } = params
|
||||||
// Build parsed article object
|
// Build parsed article object
|
||||||
const { article, hash, version, index } = await buildParsedArticleFromDraft(draft, invoice, authorPubkey)
|
const { article, hash, version, index } = await buildParsedArticleFromDraft(draft, invoice, authorPubkey)
|
||||||
|
|
||||||
@ -158,17 +163,29 @@ export function buildArticleExtraTags(draft: ArticleDraft, _category: NonNullabl
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function encryptAndPublish(
|
export async function encryptAndPublish(
|
||||||
draft: ArticleDraft,
|
params: {
|
||||||
authorPubkey: string,
|
draft: ArticleDraft
|
||||||
authorPrivateKeyForEncryption: string,
|
authorPubkey: string
|
||||||
category: NonNullable<ArticleDraft['category']>,
|
authorPrivateKeyForEncryption: string
|
||||||
|
category: NonNullable<ArticleDraft['category']>
|
||||||
presentationId: string
|
presentationId: string
|
||||||
|
}
|
||||||
): Promise<PublishedArticle> {
|
): Promise<PublishedArticle> {
|
||||||
|
const { draft, authorPubkey, authorPrivateKeyForEncryption, category, presentationId } = params
|
||||||
const { encryptedContent, key, iv } = await encryptArticleContent(draft.content)
|
const { encryptedContent, key, iv } = await encryptArticleContent(draft.content)
|
||||||
const encryptedKey = await encryptDecryptionKey(key, iv, authorPrivateKeyForEncryption, authorPubkey)
|
const encryptedKey = await encryptDecryptionKey(key, iv, authorPrivateKeyForEncryption, authorPubkey)
|
||||||
const invoice = await createArticleInvoice(draft)
|
const invoice = await createArticleInvoice(draft)
|
||||||
const extraTags = buildArticleExtraTags(draft, category)
|
const extraTags = buildArticleExtraTags(draft, category)
|
||||||
const publishResult = await publishPreview(draft, invoice, authorPubkey, presentationId, extraTags, encryptedContent, encryptedKey, true)
|
const publishResult = await publishPreview({
|
||||||
|
draft,
|
||||||
|
invoice,
|
||||||
|
authorPubkey,
|
||||||
|
presentationId,
|
||||||
|
extraTags,
|
||||||
|
encryptedContent,
|
||||||
|
encryptedKey,
|
||||||
|
returnStatus: true,
|
||||||
|
})
|
||||||
|
|
||||||
if (!publishResult) {
|
if (!publishResult) {
|
||||||
return buildFailure('Failed to publish article')
|
return buildFailure('Failed to publish article')
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user