Merge pull request #1403 from PR0M3TH3AN/codex/replace-legacy-markup-in-profile-modal

Mount DM AppShell into Profile Messages pane
This commit is contained in:
thePR0M3TH3AN authored and GitHub committed 2026-01-19 14:21:50 -05:00
commit 767c91595b
2 files changed
+52 -289

No files matched your search

+1 -289
View File
@@ -1067,295 +1067,7 @@
role="tabpanel"
aria-labelledby="profileNavMessages"
>
<p class="text-sm text-muted">
View encrypted conversations sent with NIP-04 or NIP-44. bitvid keeps message data on this device only.
</p>
<div class="card space-y-4 p-4">
<div class="flex flex-wrap items-start justify-between gap-3">
<div class="space-y-1">
<h3 class="text-sm font-semibold text-text">Direct message actions</h3>
<p class="text-xs text-muted">
Start a new DM or jump to relay preferences before you send.
</p>
</div>
<button
id="profileMessagesSendDm"
type="button"
class="btn focus-ring inline-flex items-center gap-2"
data-size="sm"
>
Send DM
</button>
</div>
<div class="flex flex-wrap items-center justify-between gap-3 border-t border-border/60 pt-3">
<div class="space-y-1">
<h4 class="text-xs font-semibold text-text">Recipient DM relays</h4>
<p class="text-xs text-muted">
Use the relays advertised in kind 10050 to prioritize encrypted delivery.
</p>
</div>
<button
id="profileMessagesOpenRelays"
type="button"
class="btn-ghost focus-ring inline-flex items-center gap-2"
data-size="sm"
>
Use DM relays
</button>
</div>
<div class="flex flex-wrap items-center justify-between gap-3 border-t border-border/60 pt-3">
<div class="space-y-1">
<h4 class="text-xs font-semibold text-text">NIP-17 privacy delivery</h4>
<p class="text-xs text-muted">
Send gift-wrapped DMs to the relays your recipient advertises in kind 10050.
</p>
</div>
<label
for="profileMessagesPrivacyToggle"
class="inline-flex items-center gap-2 text-xs font-medium text-muted-strong"
title="NIP-17 gift-wraps your DM so relays only see the wrapper and relay hints, not the plaintext. It requires the recipient to publish kind 10050 relay hints."
>
<input
id="profileMessagesPrivacyToggle"
type="checkbox"
class="checkbox"
/>
Use NIP-17
</label>
</div>
</div>
<div class="card space-y-4 p-4">
<div class="flex flex-wrap items-start justify-between gap-3">
<div class="space-y-1">
<h3 class="text-sm font-semibold text-text">Your DM relay hints</h3>
<p class="text-xs text-muted">
Publish kind 10050 so contacts can deliver NIP-17 gift-wrapped DMs to you.
</p>
</div>
<button
id="profileMessagesRelayPublish"
type="button"
class="btn focus-ring inline-flex items-center gap-2"
data-size="sm"
title="Publishing kind 10050 makes your DM relay list public so others can deliver NIP-17 messages."
>
Publish relays
</button>
</div>
<label class="flex-1 text-sm text-muted-strong" for="profileMessagesRelayInput">
<span class="mb-2 block font-medium">Add a DM relay</span>
<div class="flex flex-wrap items-center gap-2">
<input
id="profileMessagesRelayInput"
type="url"
inputmode="url"
autocomplete="off"
class="input flex-1"
placeholder="wss://relay.example.com"
/>
<button
id="profileMessagesRelayAdd"
type="button"
class="btn-ghost focus-ring inline-flex items-center gap-2"
data-size="sm"
>
Add
</button>
</div>
</label>
<ul
id="profileMessagesRelayList"
class="grid-stack"
data-orientation="vertical"
aria-live="polite"
aria-label="Your DM relay hints"
></ul>
<p
id="profileMessagesRelayStatus"
class="text-xs text-muted"
role="status"
aria-live="polite"
></p>
</div>
<div class="card space-y-4 p-4">
<div class="space-y-1">
<h3 class="text-sm font-semibold text-text">Message activity privacy</h3>
<p class="text-xs text-muted">
Read receipts and typing indicators are optional signals published to relays.
</p>
</div>
<div class="rounded-lg border border-border/60 bg-bg-muted px-3 py-2 text-xs text-muted">
Privacy warning: enabling these signals shares message activity metadata with anyone
who can access your relay events.
</div>
<div class="space-y-2">
<label
for="profileMessagesReadReceiptsToggle"
class="inline-flex items-center gap-2 text-xs font-medium text-muted-strong"
>
<input
id="profileMessagesReadReceiptsToggle"
type="checkbox"
class="checkbox"
/>
Send read receipts
</label>
<label
for="profileMessagesTypingToggle"
class="inline-flex items-center gap-2 text-xs font-medium text-muted-strong"
>
<input
id="profileMessagesTypingToggle"
type="checkbox"
class="checkbox"
/>
Share typing indicators
</label>
</div>
</div>
<div
id="profileMessagesStatus"
class="sr-only"
role="status"
aria-live="polite"
></div>
<div
id="profileMessagesLoading"
class="hidden py-6"
role="status"
aria-live="polite"
>
<div class="sidebar-loading-wrapper">
<div class="sidebar-loading-indicator">
<span
class="status-spinner status-spinner--inline"
aria-hidden="true"
></span>
<span class="sidebar-loading-text"
>Fetching direct messages from relays…</span
>
</div>
</div>
</div>
<div
id="profileMessagesError"
class="card hidden border border-critical/40 bg-critical/10 px-4 py-3 text-sm text-critical"
role="alert"
aria-live="assertive"
></div>
<div
id="profileMessagesEmpty"
class="card hidden border border-dashed border-border/60 p-6 text-center text-sm text-muted"
role="status"
aria-live="polite"
>
No direct messages yet.
</div>
<div class="flex items-center justify-end gap-2">
<button
id="profileMessagesReload"
type="button"
class="btn-ghost focus-ring inline-flex items-center gap-2"
data-size="sm"
>
Refresh
</button>
</div>
<ul
id="profileMessagesList"
class="grid-stack hidden"
data-orientation="vertical"
aria-live="polite"
aria-label="Direct message threads"
></ul>
<div
id="profileMessagesConversation"
class="hidden flex flex-col gap-3"
role="log"
aria-live="polite"
aria-label="Direct message conversation"
></div>
<p
id="profileMessagesConversationEmpty"
class="hidden text-sm text-muted"
role="status"
aria-live="polite"
>
Select a thread to view messages and attachments.
</p>
<div class="flex flex-col gap-3 border-t border-border/60 pt-4">
<label class="sr-only" for="profileMessageInput">Message</label>
<textarea
id="profileMessageInput"
class="input min-h-[var(--size-96px)]"
rows="3"
placeholder="Write a message…"
></textarea>
<div class="flex flex-col gap-2">
<input
id="profileMessageAttachmentInput"
type="file"
class="sr-only"
multiple
/>
<div class="flex flex-wrap items-center gap-2">
<button
id="profileMessageAttachmentButton"
type="button"
class="btn-ghost focus-ring inline-flex items-center gap-2"
data-size="sm"
>
Attach file
</button>
<label class="inline-flex items-center gap-2 text-xs text-muted">
<input
id="profileMessageAttachmentEncrypt"
type="checkbox"
class="checkbox"
/>
Encrypt attachments
</label>
<button
id="profileMessageAttachmentClearCache"
type="button"
class="btn-ghost focus-ring inline-flex items-center gap-2"
data-size="sm"
>
Clear attachment cache
</button>
</div>
<div
id="profileMessageAttachmentList"
class="grid-stack"
data-orientation="vertical"
></div>
</div>
<div class="flex flex-wrap items-center justify-between gap-2">
<p
id="profileMessagesComposerHelper"
class="text-xs text-muted hidden"
role="status"
aria-live="polite"
>
Sign in to send messages.
</p>
<p
id="profileMessagesPrivacyMode"
class="text-xs text-muted"
title="NIP-04 sends a direct encrypted DM; NIP-17 gift-wraps messages to reduce metadata exposure but relies on relay hints."
>
Privacy: NIP-04
</p>
<button
id="profileMessageSendBtn"
type="button"
class="btn focus-ring inline-flex items-center gap-2"
data-size="sm"
>
Send
</button>
</div>
</div>
<div id="dmAppShellMount"></div>
</section>
<section
id="profilePaneHistory"
+51
View File
@@ -15,6 +15,7 @@ import {
} from "../constants.js";
import { getBreakpointLg } from "../designSystem/metrics.js";
import { getProviderMetadata } from "../services/authProviders/index.js";
import { AppShell } from "./dm/index.js";
import { devLogger, userLogger } from "../utils/logger.js";
import {
normalizeHashtag,
@@ -1295,6 +1296,8 @@ export class ProfileModalController {
this.profileMessagesRelayStatus = null;
this.profileMessagesReadReceiptsToggle = null;
this.profileMessagesTypingToggle = null;
this.dmAppShellContainer = null;
this.dmAppShell = null;
this.profileLinkPreviewAutoToggle = null;
this.walletUriInput = null;
this.walletDefaultZapInput = null;
@@ -1608,6 +1611,8 @@ export class ProfileModalController {
document.getElementById("profileMessagesReadReceiptsToggle") || null;
this.profileMessagesTypingToggle =
document.getElementById("profileMessagesTypingToggle") || null;
this.dmAppShellContainer =
document.getElementById("dmAppShellMount") || null;
this.profileLinkPreviewAutoToggle =
document.getElementById("profileLinkPreviewAutoToggle") || null;
@@ -4038,13 +4043,59 @@ export class ProfileModalController {
void this.ensureDirectMessageSubscription(actor);
}
mountDmAppShell() {
const container =
this.dmAppShellContainer instanceof HTMLElement
? this.dmAppShellContainer
: null;
if (!container) {
return;
}
container.innerHTML = "";
try {
this.dmAppShell = new AppShell({ document });
} catch (error) {
this.dmAppShell = null;
devLogger.warn("[profileModal] Failed to mount DM app shell:", error);
return;
}
const root =
this.dmAppShell &&
typeof this.dmAppShell.getRoot === "function"
? this.dmAppShell.getRoot()
: null;
if (!(root instanceof HTMLElement)) {
devLogger.warn("[profileModal] DM app shell root missing.");
return;
}
container.appendChild(root);
}
unmountDmAppShell() {
const container =
this.dmAppShellContainer instanceof HTMLElement
? this.dmAppShellContainer
: null;
if (container) {
container.innerHTML = "";
}
this.dmAppShell = null;
}
resumeProfileMessages() {
this.messagesViewActive = true;
this.mountDmAppShell();
this.updateMessagesReloadState();
}
pauseProfileMessages() {
this.messagesViewActive = false;
this.unmountDmAppShell();
this.updateMessagesReloadState();
}