feat(mobile): haptic tick on PTT press/release and on reactions (#125)
utils/haptics.ts: tick('ptt-on' | 'ptt-off' | 'reaction') → 10/10/8 ms
navigator.vibrate, a no-op without the API (iOS), when the system prefers
reduced motion, or when the new Settings → Calls "Haptic Feedback" switch
(default on, only rendered where the API exists) is off. PTT is observed
once through pttActiveAtom so the keyboard, global-hotkey and on-screen
paths all tick; reactions tick where the reaction event is sent in the
room and thread timelines (quick bar, hover bar, sheet and emoji board
all funnel there).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
@@ -78,6 +78,7 @@ import { ImageViewer } from '../../../components/image-viewer';
|
||||
import * as css from './ThreadTimeline.css';
|
||||
import { inSameDay, minuteDifference } from '../../../utils/time';
|
||||
import { formatDayDivider } from '../../../utils/formatTimestamp';
|
||||
import { tick } from '../../../utils/haptics';
|
||||
import { createMentionElement, isEmptyEditor, moveCursor } from '../../../components/editor';
|
||||
import { useKeyDown } from '../../../hooks/useKeyDown';
|
||||
import { roomIdToReplyDraftAtomFamily } from '../../../state/room/roomInputDrafts';
|
||||
@@ -266,6 +267,7 @@ export function ThreadTimeline({ room, thread, editor }: ThreadTimelineProps) {
|
||||
const [encUrlPreview] = useSetting(settingsAtom, 'encUrlPreview');
|
||||
const showUrlPreview = room.hasEncryptionStateEvent() ? encUrlPreview : urlPreview;
|
||||
const [hour24Clock] = useSetting(settingsAtom, 'hour24Clock');
|
||||
const [hapticFeedback] = useSetting(settingsAtom, 'hapticFeedback');
|
||||
const { navigateRoom } = useRoomNavigate();
|
||||
const [dateFormatString] = useSetting(settingsAtom, 'dateFormatString');
|
||||
|
||||
@@ -573,6 +575,7 @@ export function ThreadTimeline({ room, thread, editor }: ThreadTimelineProps) {
|
||||
const rShortcode =
|
||||
shortcode ||
|
||||
(reactions.find(eventWithShortcode)?.getContent().shortcode as string | undefined);
|
||||
tick('reaction', hapticFeedback);
|
||||
mx.sendEvent(
|
||||
room.roomId,
|
||||
// A reaction on the root is a main-timeline event, not a thread reply.
|
||||
@@ -582,7 +585,7 @@ export function ThreadTimeline({ room, thread, editor }: ThreadTimelineProps) {
|
||||
getReactionContent(targetEventId, key, rShortcode),
|
||||
);
|
||||
},
|
||||
[mx, room, thread, getRelationTimelineSet],
|
||||
[mx, room, thread, getRelationTimelineSet, hapticFeedback],
|
||||
);
|
||||
|
||||
const handleEdit = useCallback(
|
||||
|
||||
Reference in New Issue
Block a user