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>
This commit is contained in:
woikos
2025-12-31 11:06:51 +01:00
parent f78138c7c4
commit fecd4fdd45
29 changed files with 3717 additions and 15 deletions

View File

@@ -64,6 +64,7 @@ import {
KeyRound,
LayoutList,
List,
MessageSquare,
Monitor,
Moon,
Palette,
@@ -155,6 +156,9 @@ export default function Settings() {
// System settings
const [filterOutOnionRelays, setFilterOutOnionRelays] = useState(storage.getFilterOutOnionRelays())
// Messaging settings
const [preferNip44, setPreferNip44] = useState(storage.getPreferNip44())
const handleLanguageChange = (value: TLanguage) => {
i18n.changeLanguage(value)
setLanguage(value)
@@ -528,6 +532,37 @@ export default function Settings() {
</AccordionItem>
)}
{/* Messaging */}
{!!pubkey && (
<AccordionItem value="messaging">
<AccordionTrigger className="px-4 hover:no-underline">
<div className="flex items-center gap-4">
<MessageSquare className="size-4" />
<span>{t('Messaging')}</span>
</div>
</AccordionTrigger>
<AccordionContent className="px-4 space-y-4">
<SettingItem>
<Label htmlFor="prefer-nip44" className="text-base font-normal">
<div>{t('Prefer NIP-44 encryption')}</div>
<div className="text-muted-foreground text-sm">
{t('Use modern encryption for new conversations')}
</div>
</Label>
<Switch
id="prefer-nip44"
checked={preferNip44}
onCheckedChange={(checked) => {
storage.setPreferNip44(checked)
setPreferNip44(checked)
dispatchSettingsChanged()
}}
/>
</SettingItem>
</AccordionContent>
</AccordionItem>
)}
{/* System */}
<AccordionItem value="system">
<AccordionTrigger className="px-4 hover:no-underline">