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', +}); +