@ai-matrx/messaging 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/react.d.cts CHANGED
@@ -943,6 +943,13 @@ declare function MessageBubble(props: {
943
943
  declare function MessageActionChips(props: {
944
944
  message: Message;
945
945
  }): ReactNode;
946
+ /**
947
+ * The standalone composer: it owns its own state. Inside `ConversationView` the
948
+ * VIEW owns it instead (`ComposerView` below) — two `useComposer` instances on
949
+ * one conversation are two independent drafts, two independent reply targets,
950
+ * and — since typing rides presence — two publishers fighting over ONE presence
951
+ * entry, which `@ai-matrx/realtime` warns about by name.
952
+ */
946
953
  declare function Composer(props: {
947
954
  conversationId: ConversationId | null;
948
955
  }): ReactNode;
package/dist/react.d.ts CHANGED
@@ -943,6 +943,13 @@ declare function MessageBubble(props: {
943
943
  declare function MessageActionChips(props: {
944
944
  message: Message;
945
945
  }): ReactNode;
946
+ /**
947
+ * The standalone composer: it owns its own state. Inside `ConversationView` the
948
+ * VIEW owns it instead (`ComposerView` below) — two `useComposer` instances on
949
+ * one conversation are two independent drafts, two independent reply targets,
950
+ * and — since typing rides presence — two publishers fighting over ONE presence
951
+ * entry, which `@ai-matrx/realtime` warns about by name.
952
+ */
946
953
  declare function Composer(props: {
947
954
  conversationId: ConversationId | null;
948
955
  }): ReactNode;
package/dist/react.js CHANGED
@@ -2029,7 +2029,12 @@ function useTypists(conversationId, participants) {
2029
2029
  const typing = useTyping(
2030
2030
  {
2031
2031
  topic: conversationId === null ? "" : conversationTopic(conversationId),
2032
- identity: { userId: host?.identity.userId ?? "" }
2032
+ identity: { userId: host?.identity.userId ?? "" },
2033
+ // READ-ONLY. This label and `useComposer` sit on the SAME topic, which is
2034
+ // one channel carrying ONE presence entry per key — so exactly one of
2035
+ // them publishes, and it is the composer that actually knows whether this
2036
+ // user is typing. Publishing here would overwrite that on every heartbeat.
2037
+ publish: false
2033
2038
  },
2034
2039
  { enabled: conversationId !== null && host !== null }
2035
2040
  );
@@ -2056,7 +2061,10 @@ function useOnlineUserIds(conversationId) {
2056
2061
  const presence = usePresence(
2057
2062
  {
2058
2063
  topic: conversationId === null ? "" : conversationTopic(conversationId),
2059
- presence: { state: { userId: host?.identity.userId ?? "" } }
2064
+ // READ-ONLY, for the same reason: `useComposer`'s typing presence already
2065
+ // puts this user in the roster under this key with their `userId`, and a
2066
+ // second publisher on one entry just fights it.
2067
+ presence: { publish: false, state: { userId: host?.identity.userId ?? "" } }
2060
2068
  },
2061
2069
  { enabled: conversationId !== null && host !== null }
2062
2070
  );
@@ -2137,7 +2145,7 @@ function useMessagingAi(conversationId) {
2137
2145
  }
2138
2146
  function useMessageAction(message) {
2139
2147
  const host = useRequiredMessagingHost();
2140
- const action = message.action;
2148
+ const action = message.action ?? null;
2141
2149
  const [receipt, setReceipt] = useState(
2142
2150
  () => action === null ? null : host.actions.receiptFor(action.kind, message.id, host.identity.userId)
2143
2151
  );
@@ -2669,7 +2677,7 @@ function ConversationView(props) {
2669
2677
  /* @__PURE__ */ jsx4(TypingDots, {}),
2670
2678
  typists.label
2671
2679
  ] }) : null }),
2672
- /* @__PURE__ */ jsx4(Composer, { conversationId })
2680
+ /* @__PURE__ */ jsx4(ComposerView, { composer, disabled: false })
2673
2681
  ] });
2674
2682
  }
2675
2683
  function MessageGroupView(props) {
@@ -2802,6 +2810,10 @@ function MessageActionChips(props) {
2802
2810
  }
2803
2811
  function Composer(props) {
2804
2812
  const composer = useComposer(props.conversationId);
2813
+ return /* @__PURE__ */ jsx4(ComposerView, { composer, disabled: props.conversationId === null });
2814
+ }
2815
+ function ComposerView(props) {
2816
+ const composer = props.composer;
2805
2817
  const textareaRef = useRef3(null);
2806
2818
  useEffect3(() => {
2807
2819
  const node = textareaRef.current;
@@ -2835,7 +2847,7 @@ function Composer(props) {
2835
2847
  value: composer.value,
2836
2848
  placeholder: "Message",
2837
2849
  "aria-label": "Message",
2838
- disabled: props.conversationId === null,
2850
+ disabled: props.disabled,
2839
2851
  onChange: (event) => {
2840
2852
  composer.setValue(event.target.value);
2841
2853
  composer.onKeystroke();