feat(messaging-ui): focusThreadId on Messenger + Inbox for search deep-links (0.1.6)
A host can pass focusThreadId to select/open a specific conversation — used by the CRM's global search to jump to the exact thread. Mail switches to Open + selects the matching item; messenger selects the thread. (Source for the already-published 0.1.6.) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@insignia/iios-messaging-ui",
|
||||
"version": "0.1.5",
|
||||
"version": "0.1.6",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.js",
|
||||
|
||||
@@ -12,7 +12,7 @@ import { ThreadPane } from './thread-pane';
|
||||
* with a channel browser when the adapter supports channels. Owns only selection + browse state;
|
||||
* all data flows through the injected adapter via the hooks.
|
||||
*/
|
||||
export function Messenger() {
|
||||
export function Messenger({ focusThreadId }: { focusThreadId?: string | null } = {}) {
|
||||
const { conversations, loading, error, refetch } = useConversations();
|
||||
const adapter = useAdapter();
|
||||
const channelsSupported = typeof adapter.browseChannels === 'function';
|
||||
@@ -32,6 +32,14 @@ export function Messenger() {
|
||||
// Switching conversations (or into browse/compose) closes any open thread pane.
|
||||
useEffect(() => setActiveRoot(null), [selected, browsing, composing]);
|
||||
|
||||
// Deep link (e.g. from global search): focus the requested conversation.
|
||||
useEffect(() => {
|
||||
if (!focusThreadId) return;
|
||||
setBrowsing(false);
|
||||
setComposing(false);
|
||||
setSelected(focusThreadId);
|
||||
}, [focusThreadId]);
|
||||
|
||||
const channels = useMemo(() => conversations.filter((c) => c.membership === 'channel'), [conversations]);
|
||||
const dms = useMemo(() => conversations.filter((c) => c.membership !== 'channel'), [conversations]);
|
||||
const selectedConversation = useMemo(() => conversations.find((c) => c.threadId === selected) ?? null, [conversations, selected]);
|
||||
|
||||
@@ -32,17 +32,30 @@ const timeOf = (iso?: string): string => {
|
||||
};
|
||||
|
||||
/** The unified inbox: work items + mail in one list; click a threaded row to read + reply. */
|
||||
export function Inbox() {
|
||||
export function Inbox({ focusThreadId }: { focusThreadId?: string | null } = {}) {
|
||||
const [filter, setFilter] = useState<InboxState>('OPEN');
|
||||
const { items, loading, error, transition, refetch } = useInbox(filter);
|
||||
const compose = useCompose();
|
||||
const [selectedId, setSelectedId] = useState<string | null>(null);
|
||||
const [composing, setComposing] = useState(false);
|
||||
|
||||
// Deep link (e.g. from global search): mail lives in the Open view, so switch there and let the
|
||||
// selection effect pick the matching thread once the list loads.
|
||||
useEffect(() => {
|
||||
if (focusThreadId) setFilter('OPEN');
|
||||
}, [focusThreadId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (focusThreadId) {
|
||||
const hit = items.find((i) => i.threadId === focusThreadId);
|
||||
if (hit) {
|
||||
setSelectedId(hit.id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (selectedId && items.some((i) => i.id === selectedId)) return;
|
||||
setSelectedId(items[0]?.id ?? null);
|
||||
}, [items, selectedId]);
|
||||
}, [items, selectedId, focusThreadId]);
|
||||
|
||||
const selected = items.find((i) => i.id === selectedId) ?? null;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user