Files
smesh/src/types/index.d.ts
woikos fecd4fdd45 Add DM inbox with NIP-04/NIP-17 support and soft delete
Features:
- Full DM inbox UI with conversation list and message view
- Support for both NIP-04 (kind 4) and NIP-17 (kind 14/1059) encryption
- Progressive message decryption with background loading
- Soft delete using kind 30078 Application Specific Data events
- Message selection UI with delete selected/delete all
- Undelete all functionality per conversation
- Jump to newest button with new message counter
- Conversation filtering (all / follows only)
- Per-conversation relay and encryption settings
- New messages indicator on sidebar (clears when inbox viewed)
- Follow indicator on conversation items

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-31 11:06:51 +01:00

268 lines
6.2 KiB
TypeScript

import { Event, Filter, VerifiedEvent } from 'nostr-tools'
import {
MEDIA_AUTO_LOAD_POLICY,
NOTIFICATION_LIST_STYLE,
NSFW_DISPLAY_POLICY,
POLL_TYPE
} from '../constants'
export type TSubRequestFilter = Omit<Filter, 'since' | 'until'> & { limit: number }
export type TFeedSubRequest = {
urls: string[]
filter: Omit<Filter, 'since' | 'until'>
}
export type TProfile = {
username: string
pubkey: string
npub: string
original_username?: string
banner?: string
avatar?: string
nip05?: string
about?: string
website?: string
lud06?: string
lud16?: string
lightningAddress?: string
created_at?: number
emojis?: TEmoji[]
}
export type TMailboxRelayScope = 'read' | 'write' | 'both'
export type TMailboxRelay = {
url: string
scope: TMailboxRelayScope
}
export type TRelayList = {
write: string[]
read: string[]
originalRelays: TMailboxRelay[]
}
export type TRelayInfo = {
url: string
shortUrl: string
name?: string
description?: string
icon?: string
pubkey?: string
contact?: string
supported_nips?: number[]
software?: string
version?: string
tags?: string[]
payments_url?: string
limitation?: {
auth_required?: boolean
payment_required?: boolean
}
}
export type TWebMetadata = {
title?: string | null
description?: string | null
image?: string | null
}
export type TRelaySet = {
id: string
aTag: string[]
name: string
relayUrls: string[]
}
export type TConfig = {
relayGroups: TRelaySet[]
theme: TThemeSetting
}
export type TThemeSetting = 'light' | 'dark' | 'system' | 'pure-black'
export type TTheme = 'light' | 'dark' | 'pure-black'
export type TDraftEvent = Pick<Event, 'content' | 'created_at' | 'kind' | 'tags'>
export type TNip07 = {
getPublicKey: () => Promise<string>
signEvent: (draftEvent: TDraftEvent) => Promise<VerifiedEvent>
nip04?: {
encrypt?: (pubkey: string, plainText: string) => Promise<string>
decrypt?: (pubkey: string, cipherText: string) => Promise<string>
}
nip44?: {
encrypt?: (pubkey: string, plainText: string) => Promise<string>
decrypt?: (pubkey: string, cipherText: string) => Promise<string>
}
}
export interface ISigner {
getPublicKey: () => Promise<string>
signEvent: (draftEvent: TDraftEvent) => Promise<VerifiedEvent>
nip04Encrypt: (pubkey: string, plainText: string) => Promise<string>
nip04Decrypt: (pubkey: string, cipherText: string) => Promise<string>
nip44Encrypt?: (pubkey: string, plainText: string) => Promise<string>
nip44Decrypt?: (pubkey: string, cipherText: string) => Promise<string>
}
export type TSignerType = 'nsec' | 'nip-07' | 'browser-nsec' | 'ncryptsec' | 'npub' | 'bunker'
export type TAccount = {
pubkey: string
signerType: TSignerType
ncryptsec?: string
nsec?: string
npub?: string
bunkerPubkey?: string
bunkerRelays?: string[]
bunkerSecret?: string
bunkerCatToken?: string
}
export type TAccountPointer = Pick<TAccount, 'pubkey' | 'signerType'>
export type TFeedType = 'following' | 'pinned' | 'relays' | 'relay'
export type TFeedInfo = { feedType: TFeedType; id?: string } | null
export type TLanguage = 'en' | 'zh' | 'pl'
export type TImetaInfo = {
url: string
blurHash?: string
thumbHash?: Uint8Array
dim?: { width: number; height: number }
pubkey?: string
}
export type TPublishOptions = {
specifiedRelayUrls?: string[]
additionalRelayUrls?: string[]
minPow?: number
}
export type TNoteListMode = 'posts' | 'postsAndReplies' | 'you' | '24h'
export type TNotificationType = 'all' | 'mentions' | 'reactions' | 'zaps'
export type TPageRef = { scrollToTop: (behavior?: ScrollBehavior) => void }
export type TEmoji = {
shortcode: string
url: string
}
export type TMediaUploadServiceConfig =
| {
type: 'nip96'
service: string
}
| {
type: 'blossom'
}
export type TPollType = (typeof POLL_TYPE)[keyof typeof POLL_TYPE]
export type TPollCreateData = {
isMultipleChoice: boolean
options: string[]
relays: string[]
endsAt?: number
}
export type TSearchType =
| 'profile'
| 'profiles'
| 'notes'
| 'note'
| 'hashtag'
| 'relay'
| 'externalContent'
| 'nak'
export type TSearchParams =
| {
type: Exclude<TSearchType, 'nak'>
search: string
input?: string
}
| {
type: 'nak'
search: string
request: TFeedSubRequest
input?: string
}
export type TNotificationStyle =
(typeof NOTIFICATION_LIST_STYLE)[keyof typeof NOTIFICATION_LIST_STYLE]
export type TAwesomeRelayCollection = {
id: string
name: string
relays: string[]
}
export type TMediaAutoLoadPolicy =
(typeof MEDIA_AUTO_LOAD_POLICY)[keyof typeof MEDIA_AUTO_LOAD_POLICY]
export type TNsfwDisplayPolicy = (typeof NSFW_DISPLAY_POLICY)[keyof typeof NSFW_DISPLAY_POLICY]
export type TSyncSettings = {
themeSetting?: TThemeSetting
primaryColor?: string
defaultZapSats?: number
defaultZapComment?: string
quickZap?: boolean
autoplay?: boolean
hideUntrustedInteractions?: boolean
hideUntrustedNotifications?: boolean
hideUntrustedNotes?: boolean
nsfwDisplayPolicy?: TNsfwDisplayPolicy
showKinds?: number[]
hideContentMentioningMutedUsers?: boolean
notificationListStyle?: TNotificationStyle
mediaAutoLoadPolicy?: TMediaAutoLoadPolicy
sidebarCollapse?: boolean
enableSingleColumnLayout?: boolean
faviconUrlTemplate?: string
filterOutOnionRelays?: boolean
quickReaction?: boolean
quickReactionEmoji?: string | TEmoji
noteListMode?: TNoteListMode
preferNip44?: boolean
}
// DM types
export type TDMEncryptionType = 'nip04' | 'nip17'
export interface TConversation {
partnerPubkey: string
lastMessageAt: number
lastMessagePreview: string
unreadCount: number
preferredEncryption: TDMEncryptionType | null
}
export interface TDirectMessage {
id: string
senderPubkey: string
recipientPubkey: string
content: string
createdAt: number
encryptionType: TDMEncryptionType
event: Event
decryptedContent?: string
seenOnRelays?: string[]
}
// Deleted messages state (stored in kind 30078 Application Specific Data)
export interface TDMDeletedState {
// Specific message IDs to ignore
deletedIds: string[]
// Timestamp ranges to ignore per conversation
deletedRanges: {
[partnerPubkey: string]: Array<{
start: number // timestamp
end: number // timestamp
}>
}
}