Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion src/components/message/MessageItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
WhisperMessage,
} from "./index";
import { MediaPreview } from "./MediaPreview";
import { MessageStatusIndicator } from "./MessageStatusIndicator";

interface MessageItemProps {
message: MessageType;
Expand Down Expand Up @@ -671,7 +672,7 @@ export const MessageItem = memo((props: MessageItemProps) => {
showHeader ? "mt-4" : "py-0.5"
}${isHighlighted ? " bg-primary/10 ring-1 ring-primary/30 rounded" : ""}${
message.status === "pending"
? " opacity-60 italic"
? " opacity-60"
: message.status === "failed"
? " opacity-60 line-through text-discord-red"
: ""
Expand Down Expand Up @@ -760,6 +761,17 @@ export const MessageItem = memo((props: MessageItemProps) => {
)}
</EnhancedLinkWrapper>

{(message.status === "pending" || message.status === "failed") && (
<span className="inline-flex" style={{ textDecoration: "none" }}>
<MessageStatusIndicator
status={message.status}
onRetry={() =>
useStore.getState().resendFailedMessage(message.id)
}
/>
</span>
)}

{/* Embedded media below text — first always visible,
known-type extras collapsed behind a "show more" toggle to prevent floods.
Null-type extras render inline since they show nothing if the probe fails. */}
Expand Down
55 changes: 55 additions & 0 deletions src/components/message/MessageStatusIndicator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { useLingui } from "@lingui/react/macro";
import { useEffect, useState } from "react";
import { RefreshIcon, SpinnerIcon } from "./icons";

// Delay before a still-pending message shows the spinner. Short enough
// to feel responsive on a slow echo, long enough that the common case
// (echo arrives in <500ms) never flashes a spinner.
const SPINNER_DELAY_MS = 500;

interface MessageStatusIndicatorProps {
status: "pending" | "failed";
onRetry?: () => void;
}

export function MessageStatusIndicator({
status,
onRetry,
}: MessageStatusIndicatorProps) {
const { t } = useLingui();
const [showSpinner, setShowSpinner] = useState(false);

useEffect(() => {
if (status !== "pending") {
setShowSpinner(false);
return;
}
const timer = setTimeout(() => setShowSpinner(true), SPINNER_DELAY_MS);
return () => clearTimeout(timer);
}, [status]);

if (status === "pending") {
if (!showSpinner) return null;
return (
<span
role="status"
className="ml-2 inline-flex items-center text-discord-text-muted align-middle"
aria-label={t`Sending`}
>
<SpinnerIcon className="animate-spin h-3 w-3" />
</span>
);
}

return (
<button
type="button"
onClick={onRetry}
className="ml-2 inline-flex items-center text-discord-text-muted hover:text-discord-red cursor-pointer bg-transparent border-none p-0 align-middle"
aria-label={t`Retry sending`}
title={t`Retry sending`}
>
<RefreshIcon className="h-3.5 w-3.5" />
</button>
);
}
32 changes: 32 additions & 0 deletions src/components/message/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,35 @@ export const MdAddReaction = ({ className }: { className?: string }) => (
<path d="M18 9V7h-2V2.84A9.929 9.929 0 0 0 11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12c0-1.05-.17-2.05-.47-3H18zm-2.5-1c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5-1.5-.67-1.5-1.5.67-1.5 1.5-1.5zm-7 0c.83 0 1.5.67 1.5 1.5S9.33 11 8.5 11 7 10.33 7 9.5 7.67 8 8.5 8zm3.5 9.5c-2.33 0-4.31-1.46-5.11-3.5h10.22c-.8 2.04-2.78 3.5-5.11 3.5zM22 3h2v2h-2v2h-2V5h-2V3h2V1h2v2z" />
</svg>
);

export const SpinnerIcon = ({ className }: { className?: string }) => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
className={className}
aria-hidden="true"
>
<circle
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="3"
opacity="0.25"
/>
<path fill="currentColor" d="M4 12a8 8 0 018-8v3a5 5 0 00-5 5H4z" />
</svg>
);

export const RefreshIcon = ({ className }: { className?: string }) => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
className={className}
aria-hidden="true"
>
<path d="M17.65 6.35A7.958 7.958 0 0 0 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08A5.99 5.99 0 0 1 12 18c-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z" />
</svg>
);
28 changes: 24 additions & 4 deletions src/lib/irc/handlers/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,24 @@ import { isChannelTarget } from "../../ircUtils";
import type { IRCClientContext } from "../IRCClientContext";
import { getNickFromNuh, getTimestampFromTags } from "../utils";

// Labeled-response wraps every multi-line server reply (e.g. PRIVMSG-to-away,
// where the server emits both 301 RPL_AWAY and the echo) in a batch whose
// opener carries the `label` tag. Inner messages only have `@batch=ID`, so
// downstream label-matching code (pending-message dedup) needs us to hoist
// the batch's label onto the message.
function inheritLabelFromBatch(
mtags: Record<string, string> | undefined,
ctx: IRCClientContext,
serverId: string,
): Record<string, string> | undefined {
if (!mtags?.batch || mtags.label) return mtags;
const batch = ctx.activeBatches.get(serverId)?.get(mtags.batch);
if (batch?.type !== "labeled-response") return mtags;
const label = batch.batchTags?.label;
if (!label) return mtags;
return { ...mtags, label };
}

export function handlePrivmsg(
ctx: IRCClientContext,
serverId: string,
Expand Down Expand Up @@ -46,24 +64,26 @@ export function handlePrivmsg(
}
}

const effectiveMtags = inheritLabelFromBatch(mtags, ctx, serverId);

if (isChannel) {
const channelName = target;
ctx.triggerEvent("CHANMSG", {
serverId,
mtags,
mtags: effectiveMtags,
sender,
channelName,
message,
timestamp: getTimestampFromTags(mtags),
timestamp: getTimestampFromTags(effectiveMtags),
});
} else {
ctx.triggerEvent("USERMSG", {
serverId,
mtags,
mtags: effectiveMtags,
sender,
target,
message,
timestamp: getTimestampFromTags(mtags),
timestamp: getTimestampFromTags(effectiveMtags),
});
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/locales/cs/messages.mjs

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions src/locales/cs/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -1989,6 +1989,11 @@ msgstr "Zobrazovat Markdown formátování ve zprávách"
msgid "Reply"
msgstr "Odpovědět"

#: src/components/message/MessageStatusIndicator.tsx
#: src/components/message/MessageStatusIndicator.tsx
msgid "Retry sending"
msgstr "Zkusit odeslat znovu"

#: src/components/ui/FloodSettingsModal.tsx
msgid "Rules"
msgstr "Pravidla"
Expand Down Expand Up @@ -2123,6 +2128,10 @@ msgstr "Odeslat soukromou zprávu"
msgid "Send Typing Notifications"
msgstr "Odesílat oznámení o psaní"

#: src/components/message/MessageStatusIndicator.tsx
msgid "Sending"
msgstr "Odesílání"

#: src/components/layout/ChannelList.tsx
#: src/components/ui/QuickActions.tsx
msgid "Server"
Expand Down
2 changes: 1 addition & 1 deletion src/locales/de/messages.mjs

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions src/locales/de/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -1989,6 +1989,11 @@ msgstr "Markdown-Formatierung in Nachrichten rendern"
msgid "Reply"
msgstr "Antworten"

#: src/components/message/MessageStatusIndicator.tsx
#: src/components/message/MessageStatusIndicator.tsx
msgid "Retry sending"
msgstr "Erneut senden"

#: src/components/ui/FloodSettingsModal.tsx
msgid "Rules"
msgstr "Regeln"
Expand Down Expand Up @@ -2123,6 +2128,10 @@ msgstr "Privatnachricht senden"
msgid "Send Typing Notifications"
msgstr "Tipp-Benachrichtigungen senden"

#: src/components/message/MessageStatusIndicator.tsx
msgid "Sending"
msgstr "Wird gesendet"

#: src/components/layout/ChannelList.tsx
#: src/components/ui/QuickActions.tsx
msgid "Server"
Expand Down
2 changes: 1 addition & 1 deletion src/locales/en/messages.mjs

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions src/locales/en/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -1988,6 +1988,11 @@ msgstr "Render markdown formatting in messages"
msgid "Reply"
msgstr "Reply"

#: src/components/message/MessageStatusIndicator.tsx
#: src/components/message/MessageStatusIndicator.tsx
msgid "Retry sending"
msgstr "Retry sending"

#: src/components/ui/FloodSettingsModal.tsx
msgid "Rules"
msgstr "Rules"
Expand Down Expand Up @@ -2122,6 +2127,10 @@ msgstr "Send private message"
msgid "Send Typing Notifications"
msgstr "Send Typing Notifications"

#: src/components/message/MessageStatusIndicator.tsx
msgid "Sending"
msgstr "Sending"

#: src/components/layout/ChannelList.tsx
#: src/components/ui/QuickActions.tsx
msgid "Server"
Expand Down
2 changes: 1 addition & 1 deletion src/locales/es/messages.mjs

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions src/locales/es/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -1989,6 +1989,11 @@ msgstr "Renderizar formato Markdown en mensajes"
msgid "Reply"
msgstr "Responder"

#: src/components/message/MessageStatusIndicator.tsx
#: src/components/message/MessageStatusIndicator.tsx
msgid "Retry sending"
msgstr "Reintentar envío"

#: src/components/ui/FloodSettingsModal.tsx
msgid "Rules"
msgstr "Reglas"
Expand Down Expand Up @@ -2123,6 +2128,10 @@ msgstr "Enviar mensaje privado"
msgid "Send Typing Notifications"
msgstr "Enviar notificaciones de escritura"

#: src/components/message/MessageStatusIndicator.tsx
msgid "Sending"
msgstr "Enviando"

#: src/components/layout/ChannelList.tsx
#: src/components/ui/QuickActions.tsx
msgid "Server"
Expand Down
2 changes: 1 addition & 1 deletion src/locales/fi/messages.mjs

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions src/locales/fi/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -1989,6 +1989,11 @@ msgstr "Näytä Markdown-muotoilu viesteissä"
msgid "Reply"
msgstr "Vastaa"

#: src/components/message/MessageStatusIndicator.tsx
#: src/components/message/MessageStatusIndicator.tsx
msgid "Retry sending"
msgstr "Yritä lähettää uudelleen"

#: src/components/ui/FloodSettingsModal.tsx
msgid "Rules"
msgstr "Säännöt"
Expand Down Expand Up @@ -2123,6 +2128,10 @@ msgstr "Lähetä yksityisviesti"
msgid "Send Typing Notifications"
msgstr "Lähetä kirjoitusilmoituksia"

#: src/components/message/MessageStatusIndicator.tsx
msgid "Sending"
msgstr "Lähetetään"

#: src/components/layout/ChannelList.tsx
#: src/components/ui/QuickActions.tsx
msgid "Server"
Expand Down
2 changes: 1 addition & 1 deletion src/locales/fr/messages.mjs

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions src/locales/fr/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -1989,6 +1989,11 @@ msgstr "Afficher le formatage Markdown dans les messages"
msgid "Reply"
msgstr "Répondre"

#: src/components/message/MessageStatusIndicator.tsx
#: src/components/message/MessageStatusIndicator.tsx
msgid "Retry sending"
msgstr "Réessayer l'envoi"

#: src/components/ui/FloodSettingsModal.tsx
msgid "Rules"
msgstr "Règles"
Expand Down Expand Up @@ -2123,6 +2128,10 @@ msgstr "Envoyer un message privé"
msgid "Send Typing Notifications"
msgstr "Envoyer des notifications de frappe"

#: src/components/message/MessageStatusIndicator.tsx
msgid "Sending"
msgstr "Envoi en cours"

#: src/components/layout/ChannelList.tsx
#: src/components/ui/QuickActions.tsx
msgid "Server"
Expand Down
2 changes: 1 addition & 1 deletion src/locales/it/messages.mjs

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions src/locales/it/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -1989,6 +1989,11 @@ msgstr "Mostra la formattazione Markdown nei messaggi"
msgid "Reply"
msgstr "Rispondi"

#: src/components/message/MessageStatusIndicator.tsx
#: src/components/message/MessageStatusIndicator.tsx
msgid "Retry sending"
msgstr "Riprova invio"

#: src/components/ui/FloodSettingsModal.tsx
msgid "Rules"
msgstr "Regole"
Expand Down Expand Up @@ -2123,6 +2128,10 @@ msgstr "Invia messaggio privato"
msgid "Send Typing Notifications"
msgstr "Invia notifiche di digitazione"

#: src/components/message/MessageStatusIndicator.tsx
msgid "Sending"
msgstr "Invio in corso"

#: src/components/layout/ChannelList.tsx
#: src/components/ui/QuickActions.tsx
msgid "Server"
Expand Down
2 changes: 1 addition & 1 deletion src/locales/ja/messages.mjs

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions src/locales/ja/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -1989,6 +1989,11 @@ msgstr "メッセージ内のMarkdown書式を表示する"
msgid "Reply"
msgstr "返信"

#: src/components/message/MessageStatusIndicator.tsx
#: src/components/message/MessageStatusIndicator.tsx
msgid "Retry sending"
msgstr "再送信"

#: src/components/ui/FloodSettingsModal.tsx
msgid "Rules"
msgstr "ルール"
Expand Down Expand Up @@ -2123,6 +2128,10 @@ msgstr "プライベートメッセージを送信"
msgid "Send Typing Notifications"
msgstr "入力中通知を送信する"

#: src/components/message/MessageStatusIndicator.tsx
msgid "Sending"
msgstr "送信中"

#: src/components/layout/ChannelList.tsx
#: src/components/ui/QuickActions.tsx
msgid "Server"
Expand Down
2 changes: 1 addition & 1 deletion src/locales/ko/messages.mjs

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions src/locales/ko/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -1989,6 +1989,11 @@ msgstr "메시지에서 마크다운 서식 렌더링"
msgid "Reply"
msgstr "답장"

#: src/components/message/MessageStatusIndicator.tsx
#: src/components/message/MessageStatusIndicator.tsx
msgid "Retry sending"
msgstr "다시 보내기"

#: src/components/ui/FloodSettingsModal.tsx
msgid "Rules"
msgstr "규칙"
Expand Down Expand Up @@ -2123,6 +2128,10 @@ msgstr "비공개 메시지 보내기"
msgid "Send Typing Notifications"
msgstr "입력 중 알림 보내기"

#: src/components/message/MessageStatusIndicator.tsx
msgid "Sending"
msgstr "보내는 중"

#: src/components/layout/ChannelList.tsx
#: src/components/ui/QuickActions.tsx
msgid "Server"
Expand Down
2 changes: 1 addition & 1 deletion src/locales/nl/messages.mjs

Large diffs are not rendered by default.

Loading
Loading