41 lines
1.9 KiB
TypeScript
41 lines
1.9 KiB
TypeScript
/**
|
|
* Per-message text-selection mode for the chat surface. When the user taps
|
|
* "Select Text" in a chat bubble's long-press action sheet
|
|
* (`components/chat/message-long-press.tsx` → `useChatMessageLongPress`),
|
|
* the targeted message id is parked here. The bubble row reads this store
|
|
* and, when matched, (a) drops the `Pressable.onLongPress` wrapper so the
|
|
* long-press gesture no longer races with text-selection, and (b) sets
|
|
* `selectable={true}` on the Markdown / Text body — the next long-press
|
|
* inside the bubble fires UIKit's native selection magnifier + handles +
|
|
* Copy/Look Up callout.
|
|
*
|
|
* Why a separate Zustand store (not props / context, and not reused from
|
|
* the comment surface):
|
|
* - Only one message can be in selection mode at a time across the app —
|
|
* selecting message B implicitly clears message A by id replacement.
|
|
* - The flip happens from inside the context-menu callback, which lives
|
|
* in a different component tree than the chat list — easier to wire
|
|
* via a global store than to thread callbacks through every parent.
|
|
* - Chat and comment ids share no namespace constraint, and the timeline-
|
|
* list's scroll-clear handler reads the comment store specifically;
|
|
* reusing it would let a comment scroll wipe a chat selection (or
|
|
* vice versa) and let id collisions cross-trigger selection state.
|
|
*
|
|
* Lifecycle: cleared when (a) the user taps the floating Done pill,
|
|
* (b) the chat list scrolls, or (c) the chat tab loses focus —
|
|
* so each fresh navigation into chat starts with no message selected.
|
|
*/
|
|
import { create } from "zustand";
|
|
|
|
interface State {
|
|
selectingId: string | null;
|
|
setSelecting: (messageId: string) => void;
|
|
clear: () => void;
|
|
}
|
|
|
|
export const useChatSelectStore = create<State>((set) => ({
|
|
selectingId: null,
|
|
setSelecting: (messageId) => set({ selectingId: messageId }),
|
|
clear: () => set({ selectingId: null }),
|
|
}));
|