feat: typing indicator orange dots, push-to-deafen hotkey, night light filter, message length counter
CI / Build & Quality Checks (push) Failing after 5m39s
CI / Build & Quality Checks (push) Failing after 5m39s
- #108: TypingIndicator reads lotusTerminal setting; applies var(--lt-accent-orange) to container so dots inherit via backgroundColor:currentColor - #100: CallControls registers KeyM as push-to-deafen (e.code, e.repeat guard, ownerDocument.body iframe-safe editable check, [callEmbed] dep array) - P5-5: nightLightEnabled/nightLightOpacity settings; position:fixed rgba(255,140,0) overlay inside JotaiProvider; Night Light tile + intensity slider (5–80%) in Settings → Appearance - #101: RoomInput charCount state via Slate onChange + toPlainText; resets on room switch; displayed before send button when count > 0 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -196,6 +196,29 @@ export function CallControls({ callEmbed }: CallControlsProps) {
|
||||
// microphone intentionally read via microphoneRef — excluded from deps to avoid listener churn
|
||||
}, [pttMode, pttKey, callEmbed]);
|
||||
|
||||
useEffect(() => {
|
||||
const isEditable = (el: HTMLElement): boolean => {
|
||||
const tag = el.tagName;
|
||||
if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') return true;
|
||||
let node: HTMLElement | null = el;
|
||||
while (node && node !== el.ownerDocument.body) {
|
||||
if (node.contentEditable === 'true') return true;
|
||||
if (node.contentEditable === 'false') return false;
|
||||
node = node.parentElement;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
const onKeyDown = (e: KeyboardEvent) => {
|
||||
if (e.code !== 'KeyM') return;
|
||||
if (e.repeat) return;
|
||||
if (isEditable(e.target as HTMLElement)) return;
|
||||
e.preventDefault();
|
||||
callEmbed.control.toggleSound();
|
||||
};
|
||||
window.addEventListener('keydown', onKeyDown);
|
||||
return () => window.removeEventListener('keydown', onKeyDown);
|
||||
}, [callEmbed]);
|
||||
|
||||
const [hangupState, hangup] = useAsyncCallback(
|
||||
useCallback(() => callEmbed.hangup(), [callEmbed]),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user