diff --git a/src/app/components/GifPicker.tsx b/src/app/components/GifPicker.tsx
index 1ff3267b4..bd403cd5e 100644
--- a/src/app/components/GifPicker.tsx
+++ b/src/app/components/GifPicker.tsx
@@ -8,41 +8,6 @@ import { settingsAtom } from '../state/settings';
const PICKER_WIDTH = 312;
-const TERMINAL_CSS = `
- [data-gif-terminal] input,
- [data-gif-terminal] form {
- background: #030c14 !important;
- color: #e8edf5 !important;
- font-family: 'JetBrains Mono', 'Cascadia Code', 'Fira Code', monospace !important;
- border: 1px solid rgba(255,107,0,0.35) !important;
- border-radius: 4px !important;
- font-size: 12px !important;
- box-shadow: none !important;
- }
- [data-gif-terminal] input:focus {
- border-color: rgba(255,107,0,0.7) !important;
- box-shadow: 0 0 0 2px rgba(255,107,0,0.12) !important;
- outline: none !important;
- }
- [data-gif-terminal] input::placeholder {
- color: rgba(255,107,0,0.4) !important;
- font-family: 'JetBrains Mono', monospace !important;
- }
- [data-gif-terminal] svg,
- [data-gif-terminal] button[type="reset"] {
- display: none !important;
- }
- [data-gif-terminal] ::-webkit-scrollbar {
- width: 4px;
- }
- [data-gif-terminal] ::-webkit-scrollbar-track {
- background: #030508;
- }
- [data-gif-terminal] ::-webkit-scrollbar-thumb {
- background: rgba(255,107,0,0.4);
- border-radius: 2px;
- }
-`;
type GifPickerInnerProps = {
onSelect: (url: string, width: number, height: number) => void;
@@ -142,7 +107,6 @@ export function GifPicker({ apiKey, onSelect, requestClose }: GifPickerProps) {
data-gif-terminal={lotusTerminal ? '' : undefined}
style={containerStyle}
>
- {lotusTerminal && }
diff --git a/src/app/features/room/message/Message.tsx b/src/app/features/room/message/Message.tsx
index 03c9c6927..6ec8af156 100644
--- a/src/app/features/room/message/Message.tsx
+++ b/src/app/features/room/message/Message.tsx
@@ -32,7 +32,7 @@ import React, {
} from 'react';
import FocusTrap from 'focus-trap-react';
import { useHover, useFocusWithin } from 'react-aria';
-import { MatrixEvent, Room } from 'matrix-js-sdk';
+import { MatrixEvent, Room, EventStatus } from 'matrix-js-sdk';
import { Relations } from 'matrix-js-sdk/lib/models/relations';
import classNames from 'classnames';
import { RoomPinnedEventsEventContent } from 'matrix-js-sdk/lib/types';
@@ -60,6 +60,8 @@ import {
} from '../../../utils/matrix';
import { MessageLayout, MessageSpacing } from '../../../state/settings';
import { useMatrixClient } from '../../../hooks/useMatrixClient';
+import { useSetting } from '../../../state/hooks/settings';
+import { settingsAtom } from '../../../state/settings';
import { useRecentEmoji } from '../../../hooks/useRecentEmoji';
import * as css from './styles.css';
import { EventReaders } from '../../../components/event-readers';
@@ -82,6 +84,44 @@ import { PowerIcon } from '../../../components/power';
import colorMXID from '../../../../util/colorMXID';
import { getPowerTagIconSrc } from '../../../hooks/useMemberPowerTag';
+
+// Delivery status indicator for own messages
+function DeliveryStatus({ status, lotusTerminal }: { status: string | null; lotusTerminal: boolean }) {
+ if (status === null) return null; // confirmed by server — read receipts take over
+ let icon: string;
+ let label: string;
+ let colorStyle: string;
+ if (status === EventStatus.NOT_SENT) {
+ icon = '✕'; label = 'Failed to send'; colorStyle = lotusTerminal ? '#FF3B3B' : color.Critical.Main;
+ } else if (status === EventStatus.SENDING || status === EventStatus.ENCRYPTING) {
+ icon = '⟳'; label = 'Sending...'; colorStyle = lotusTerminal ? 'rgba(0,212,255,0.60)' : color.Secondary.Main;
+ } else {
+ icon = '✓'; label = 'Sent'; colorStyle = lotusTerminal ? 'rgba(0,212,255,0.70)' : color.Secondary.Main;
+ }
+ return (
+
+ {icon}
+
+ );
+}
+
export type ReactionHandler = (keyOrMxc: string, shortcode: string) => void;
type MessageQuickReactionsProps = {
@@ -727,6 +767,8 @@ export const Message = as<'div', MessageProps>(
const readReceiptUsers = hideReadReceipts
? []
: (readPositions.get(mEvent.getId() ?? '') ?? []);
+ const isMine = mEvent.getSender() === mx.getUserId();
+ const [lotusTerminal] = useSetting(settingsAtom, 'lotusTerminal');
const [hover, setHover] = useState(false);
const { hoverProps } = useHover({ onHoverChange: setHover });
@@ -846,6 +888,9 @@ export const Message = as<'div', MessageProps>(
userIds={readReceiptUsers}
/>
)}
+ {isMine && readReceiptUsers.length === 0 && (
+
+ )}
);
diff --git a/src/lotus-terminal.css.ts b/src/lotus-terminal.css.ts
index 3255516cd..0a8860f4b 100644
--- a/src/lotus-terminal.css.ts
+++ b/src/lotus-terminal.css.ts
@@ -626,3 +626,37 @@ globalStyle(`html[data-theme="light"] body.${lotusTerminalBodyClass} button[data
boxShadow: '0 0 7px rgba(196,78,0,0.18)',
});
+// ── GIF picker (terminal mode) ───────────────────────────────────────────────
+globalStyle(`body.${lotusTerminalBodyClass} [data-gif-terminal] input,` +
+ `body.${lotusTerminalBodyClass} [data-gif-terminal] form`, {
+ background: '#030c14 !important' as any,
+ color: '#e8edf5 !important' as any,
+ fontFamily: "'JetBrains Mono','Cascadia Code','Fira Code',monospace !important" as any,
+ border: '1px solid rgba(255,107,0,0.35) !important' as any,
+ borderRadius: '4px !important' as any,
+ fontSize: '12px !important' as any,
+ boxShadow: 'none !important' as any,
+});
+globalStyle(`body.${lotusTerminalBodyClass} [data-gif-terminal] input:focus`, {
+ borderColor: 'rgba(255,107,0,0.70) !important' as any,
+ boxShadow: '0 0 0 2px rgba(255,107,0,0.12) !important' as any,
+ outline: 'none !important' as any,
+});
+globalStyle(`body.${lotusTerminalBodyClass} [data-gif-terminal] input::placeholder`, {
+ color: 'rgba(255,107,0,0.40) !important' as any,
+});
+globalStyle(`body.${lotusTerminalBodyClass} [data-gif-terminal] svg,` +
+ `body.${lotusTerminalBodyClass} [data-gif-terminal] button[type="reset"]`, {
+ display: 'none !important' as any,
+});
+globalStyle(`body.${lotusTerminalBodyClass} [data-gif-terminal] ::-webkit-scrollbar`, {
+ width: '4px',
+});
+globalStyle(`body.${lotusTerminalBodyClass} [data-gif-terminal] ::-webkit-scrollbar-track`, {
+ background: '#030508',
+});
+globalStyle(`body.${lotusTerminalBodyClass} [data-gif-terminal] ::-webkit-scrollbar-thumb`, {
+ background: 'rgba(255,107,0,0.40)',
+ borderRadius: '2px',
+});
+