@samirify/messenger 0.1.0 → 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/chunk-42TCO5DV.cjs +214 -0
- package/dist/chunk-42TCO5DV.cjs.map +1 -0
- package/dist/chunk-M2F3K6UX.cjs +82 -0
- package/dist/chunk-M2F3K6UX.cjs.map +1 -0
- package/dist/chunk-O5XNJHGZ.js +198 -0
- package/dist/chunk-O5XNJHGZ.js.map +1 -0
- package/dist/chunk-OTJZXVON.js +77 -0
- package/dist/chunk-OTJZXVON.js.map +1 -0
- package/dist/index.cjs +78 -281
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -26
- package/dist/index.d.ts +5 -26
- package/dist/index.js +3 -263
- package/dist/index.js.map +1 -1
- package/dist/native/index.cjs +34 -206
- package/dist/native/index.cjs.map +1 -1
- package/dist/native/index.js +6 -178
- package/dist/native/index.js.map +1 -1
- package/dist/uiController-CM_cznOa.d.cts +26 -0
- package/dist/uiController-CNCLZw4I.d.ts +26 -0
- package/dist/web/index.cjs +63 -259
- package/dist/web/index.cjs.map +1 -1
- package/dist/web/index.d.cts +1 -0
- package/dist/web/index.d.ts +1 -0
- package/dist/web/index.js +10 -228
- package/dist/web/index.js.map +1 -1
- package/package.json +1 -1
package/dist/native/index.js
CHANGED
|
@@ -1,138 +1,8 @@
|
|
|
1
|
+
import { useMessengerConfig, useThreads, useOpenThread, MessengerI18n, useThread, useSendMessage } from '../chunk-O5XNJHGZ.js';
|
|
1
2
|
import { View, TouchableOpacity, Text, ScrollView, ActivityIndicator, RefreshControl, Image, TextInput, Platform, KeyboardAvoidingView, FlatList } from 'react-native';
|
|
2
|
-
import { createContext, useState, useRef, useContext } from 'react';
|
|
3
3
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
|
-
import {
|
|
4
|
+
import { useState, useRef } from 'react';
|
|
5
5
|
|
|
6
|
-
// src/native/InboxScreen.tsx
|
|
7
|
-
var MessengerContext = createContext(null);
|
|
8
|
-
function useMessengerConfig() {
|
|
9
|
-
const ctx = useContext(MessengerContext);
|
|
10
|
-
if (!ctx) {
|
|
11
|
-
throw new Error(
|
|
12
|
-
"@gymlium/messenger: useMessengerConfig must be used within MessengerProvider"
|
|
13
|
-
);
|
|
14
|
-
}
|
|
15
|
-
return ctx;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// src/api.ts
|
|
19
|
-
async function listThreads(http) {
|
|
20
|
-
const res = await http.getJson(
|
|
21
|
-
"/api/messages/threads"
|
|
22
|
-
);
|
|
23
|
-
return { ...res, data: res.data?.threads ?? [] };
|
|
24
|
-
}
|
|
25
|
-
async function openThread(http, clientUserId) {
|
|
26
|
-
return http.postJson("/api/messages/threads", {
|
|
27
|
-
...clientUserId ? { client_user_id: clientUserId } : {}
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
async function getThread(http, threadId, limit = 50, beforeId) {
|
|
31
|
-
const params = new URLSearchParams({ limit: String(limit) });
|
|
32
|
-
return http.getJson(`/api/messages/threads/${threadId}?${params.toString()}`);
|
|
33
|
-
}
|
|
34
|
-
async function sendMessage(http, threadId, body, image) {
|
|
35
|
-
const path = `/api/messages/threads/${threadId}/messages`;
|
|
36
|
-
if (image?.uri || image?.file) {
|
|
37
|
-
const form = new FormData();
|
|
38
|
-
if (body.trim()) form.append("body", body.trim());
|
|
39
|
-
const filename = image.name ?? image.uri?.split("/").pop() ?? "photo.jpg";
|
|
40
|
-
const match = /\.(\w+)$/.exec(filename);
|
|
41
|
-
const type = image.type ?? (match ? `image/${match[1]}` : "image/jpeg");
|
|
42
|
-
if (image.file) {
|
|
43
|
-
form.append("image", image.file, filename);
|
|
44
|
-
} else if (image.uri.startsWith("blob:") || image.uri.startsWith("data:")) {
|
|
45
|
-
const blob = await fetch(image.uri).then((r) => r.blob());
|
|
46
|
-
form.append("image", blob, filename);
|
|
47
|
-
} else {
|
|
48
|
-
form.append("image", {
|
|
49
|
-
uri: image.uri,
|
|
50
|
-
name: filename,
|
|
51
|
-
type
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
return http.postForm(path, form);
|
|
55
|
-
}
|
|
56
|
-
return http.postJson(path, { body });
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// src/queryKeys.ts
|
|
60
|
-
var messengerKeys = {
|
|
61
|
-
all: ["messenger"],
|
|
62
|
-
threads: () => [...messengerKeys.all, "threads"],
|
|
63
|
-
thread: (id) => [...messengerKeys.all, "thread", id]
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
// src/hooks/useThreads.ts
|
|
67
|
-
function useThreads(options) {
|
|
68
|
-
const { http, enabled: featureOn } = useMessengerConfig();
|
|
69
|
-
const enabled = featureOn;
|
|
70
|
-
return useQuery({
|
|
71
|
-
queryKey: messengerKeys.threads(),
|
|
72
|
-
queryFn: async () => {
|
|
73
|
-
const res = await listThreads(http);
|
|
74
|
-
if (!res.success) {
|
|
75
|
-
throw new Error(res.message ?? "Failed to load threads");
|
|
76
|
-
}
|
|
77
|
-
return res.data;
|
|
78
|
-
},
|
|
79
|
-
enabled
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
function useOpenThread() {
|
|
83
|
-
const { http, navigation } = useMessengerConfig();
|
|
84
|
-
const qc = useQueryClient();
|
|
85
|
-
return useMutation({
|
|
86
|
-
mutationFn: async (clientUserId) => {
|
|
87
|
-
const res = await openThread(http, clientUserId);
|
|
88
|
-
if (!res.success || !res.data?.thread?.id) {
|
|
89
|
-
throw new Error(res.message ?? "Could not open thread");
|
|
90
|
-
}
|
|
91
|
-
return res.data.thread;
|
|
92
|
-
},
|
|
93
|
-
onSuccess: (thread) => {
|
|
94
|
-
void qc.invalidateQueries({ queryKey: messengerKeys.threads() });
|
|
95
|
-
navigation.openThread(thread.id);
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// src/i18nKeys.ts
|
|
101
|
-
var MessengerI18n = {
|
|
102
|
-
off: {
|
|
103
|
-
key: "mobile.messenger.off",
|
|
104
|
-
fallback: "Messaging is not enabled for this account."
|
|
105
|
-
},
|
|
106
|
-
inbox: { key: "mobile.messenger.inbox", fallback: "Chat" },
|
|
107
|
-
chat: { key: "mobile.messenger.chat", fallback: "Chat" },
|
|
108
|
-
messageCoach: {
|
|
109
|
-
key: "mobile.messenger.messageCoach",
|
|
110
|
-
fallback: "Message your coach"
|
|
111
|
-
},
|
|
112
|
-
empty: {
|
|
113
|
-
key: "mobile.messenger.empty",
|
|
114
|
-
fallback: "No conversations yet"
|
|
115
|
-
},
|
|
116
|
-
yourCoach: {
|
|
117
|
-
key: "mobile.messenger.yourCoach",
|
|
118
|
-
fallback: "Your coach"
|
|
119
|
-
},
|
|
120
|
-
photo: { key: "mobile.messenger.photo", fallback: "Photo" },
|
|
121
|
-
noMessages: {
|
|
122
|
-
key: "mobile.messenger.noMessages",
|
|
123
|
-
fallback: "No messages yet"
|
|
124
|
-
},
|
|
125
|
-
startConversation: {
|
|
126
|
-
key: "mobile.messenger.startConversation",
|
|
127
|
-
fallback: "Say hello \u2014 send the first message."
|
|
128
|
-
},
|
|
129
|
-
typeMessage: {
|
|
130
|
-
key: "mobile.messenger.typeMessage",
|
|
131
|
-
fallback: "Type a message\u2026"
|
|
132
|
-
},
|
|
133
|
-
client: { key: "mobile.trainer.client", fallback: "Client" },
|
|
134
|
-
back: { key: "common.back", fallback: "Back" }
|
|
135
|
-
};
|
|
136
6
|
function FeatureOff() {
|
|
137
7
|
const { t, theme, navigation, onFeatureOff } = useMessengerConfig();
|
|
138
8
|
if (onFeatureOff) return /* @__PURE__ */ jsx(Fragment, { children: onFeatureOff() });
|
|
@@ -254,7 +124,7 @@ function InboxScreen() {
|
|
|
254
124
|
const { enabled, user, t, isRtl, theme, navigation } = useMessengerConfig();
|
|
255
125
|
const { colors, accentColor, fonts } = theme;
|
|
256
126
|
const threadsQuery = useThreads();
|
|
257
|
-
const
|
|
127
|
+
const openThread = useOpenThread();
|
|
258
128
|
if (!enabled) return /* @__PURE__ */ jsx(FeatureOff, {});
|
|
259
129
|
const threads = threadsQuery.data ?? [];
|
|
260
130
|
const loading = threadsQuery.isLoading && threads.length === 0;
|
|
@@ -304,8 +174,8 @@ function InboxScreen() {
|
|
|
304
174
|
user?.role === "client" && threads.length === 0 && /* @__PURE__ */ jsx(
|
|
305
175
|
TouchableOpacity,
|
|
306
176
|
{
|
|
307
|
-
onPress: () =>
|
|
308
|
-
disabled:
|
|
177
|
+
onPress: () => openThread.mutate(void 0),
|
|
178
|
+
disabled: openThread.isPending,
|
|
309
179
|
style: {
|
|
310
180
|
marginBottom: 14,
|
|
311
181
|
paddingVertical: 14,
|
|
@@ -313,7 +183,7 @@ function InboxScreen() {
|
|
|
313
183
|
backgroundColor: accentColor,
|
|
314
184
|
alignItems: "center"
|
|
315
185
|
},
|
|
316
|
-
children:
|
|
186
|
+
children: openThread.isPending ? /* @__PURE__ */ jsx(ActivityIndicator, { color: "#FFF" }) : /* @__PURE__ */ jsx(
|
|
317
187
|
Text,
|
|
318
188
|
{
|
|
319
189
|
style: {
|
|
@@ -362,48 +232,6 @@ function InboxScreen() {
|
|
|
362
232
|
)
|
|
363
233
|
] });
|
|
364
234
|
}
|
|
365
|
-
var POLL_MS = 18e3;
|
|
366
|
-
function useThread(threadId, options) {
|
|
367
|
-
const { http, enabled: featureOn } = useMessengerConfig();
|
|
368
|
-
const enabled = featureOn && Number.isFinite(threadId) && threadId > 0;
|
|
369
|
-
const poll = true;
|
|
370
|
-
return useQuery({
|
|
371
|
-
queryKey: messengerKeys.thread(threadId),
|
|
372
|
-
queryFn: async () => {
|
|
373
|
-
const res = await getThread(http, threadId);
|
|
374
|
-
if (!res.success) {
|
|
375
|
-
throw new Error(res.message ?? "Failed to load thread");
|
|
376
|
-
}
|
|
377
|
-
return res.data;
|
|
378
|
-
},
|
|
379
|
-
enabled,
|
|
380
|
-
refetchInterval: enabled && poll ? POLL_MS : false
|
|
381
|
-
});
|
|
382
|
-
}
|
|
383
|
-
function useSendMessage(threadId) {
|
|
384
|
-
const { http } = useMessengerConfig();
|
|
385
|
-
const qc = useQueryClient();
|
|
386
|
-
return useMutation({
|
|
387
|
-
mutationFn: async (input) => {
|
|
388
|
-
const res = await sendMessage(http, threadId, input.body, input.image);
|
|
389
|
-
if (!res.success || !res.data?.message) {
|
|
390
|
-
throw new Error(res.message ?? "Send failed");
|
|
391
|
-
}
|
|
392
|
-
return res.data.message;
|
|
393
|
-
},
|
|
394
|
-
onSuccess: (message) => {
|
|
395
|
-
qc.setQueryData(
|
|
396
|
-
messengerKeys.thread(threadId),
|
|
397
|
-
(prev) => {
|
|
398
|
-
if (!prev) return prev;
|
|
399
|
-
if (prev.messages.some((m) => m.id === message.id)) return prev;
|
|
400
|
-
return { ...prev, messages: [...prev.messages, message] };
|
|
401
|
-
}
|
|
402
|
-
);
|
|
403
|
-
void qc.invalidateQueries({ queryKey: messengerKeys.threads() });
|
|
404
|
-
}
|
|
405
|
-
});
|
|
406
|
-
}
|
|
407
235
|
function MessageBubble({ message }) {
|
|
408
236
|
const { user, isRtl, theme } = useMessengerConfig();
|
|
409
237
|
const { colors, accentColor, fonts } = theme;
|
package/dist/native/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/provider.tsx","../../src/api.ts","../../src/queryKeys.ts","../../src/hooks/useThreads.ts","../../src/hooks/useOpenThread.ts","../../src/i18nKeys.ts","../../src/native/InboxScreen.tsx","../../src/hooks/useThread.ts","../../src/hooks/useSendMessage.ts","../../src/native/MessageBubble.tsx","../../src/native/Composer.tsx","../../src/native/ThreadScreen.tsx"],"names":["jsx","openThread","useQuery","useQueryClient","useMutation","jsxs","View","Text","TouchableOpacity","ActivityIndicator","FeatureOff","Fragment","Platform"],"mappings":"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","file":"index.js","sourcesContent":["import React, { createContext, useContext, type ReactNode } from \"react\";\nimport type { MessengerConfig } from \"./types\";\n\nconst MessengerContext = createContext<MessengerConfig | null>(null);\n\nexport function MessengerProvider({\n config,\n children,\n}: {\n config: MessengerConfig;\n children: ReactNode;\n}) {\n return (\n <MessengerContext.Provider value={config}>\n {children}\n </MessengerContext.Provider>\n );\n}\n\nexport function useMessengerConfig(): MessengerConfig {\n const ctx = useContext(MessengerContext);\n if (!ctx) {\n throw new Error(\n \"@gymlium/messenger: useMessengerConfig must be used within MessengerProvider\"\n );\n }\n return ctx;\n}\n\n/** Safe variant for optional host chrome (returns null outside provider). */\nexport function useOptionalMessengerConfig(): MessengerConfig | null {\n return useContext(MessengerContext);\n}\n","import type {\n ApiResult,\n ChatMessage,\n MessageThread,\n MessengerHttp,\n PickedImage,\n} from \"./types\";\n\nexport async function listThreads(\n http: MessengerHttp\n): Promise<ApiResult<MessageThread[]>> {\n const res = await http.getJson<{ threads: MessageThread[] }>(\n \"/api/messages/threads\"\n );\n return { ...res, data: res.data?.threads ?? [] };\n}\n\nexport async function openThread(\n http: MessengerHttp,\n clientUserId?: number\n): Promise<ApiResult<{ thread: MessageThread }>> {\n return http.postJson<{ thread: MessageThread }>(\"/api/messages/threads\", {\n ...(clientUserId ? { client_user_id: clientUserId } : {}),\n });\n}\n\nexport async function getThread(\n http: MessengerHttp,\n threadId: number,\n limit = 50,\n beforeId?: number\n): Promise<ApiResult<{ thread: MessageThread; messages: ChatMessage[] }>> {\n const params = new URLSearchParams({ limit: String(limit) });\n if (beforeId != null) params.set(\"before_id\", String(beforeId));\n return http.getJson(`/api/messages/threads/${threadId}?${params.toString()}`);\n}\n\nexport async function sendMessage(\n http: MessengerHttp,\n threadId: number,\n body: string,\n image?: PickedImage | null\n): Promise<ApiResult<{ message: ChatMessage }>> {\n const path = `/api/messages/threads/${threadId}/messages`;\n if (image?.uri || image?.file) {\n const form = new FormData();\n if (body.trim()) form.append(\"body\", body.trim());\n const filename =\n image.name ??\n image.uri?.split(\"/\").pop() ??\n \"photo.jpg\";\n const match = /\\.(\\w+)$/.exec(filename);\n const type =\n image.type ?? (match ? `image/${match[1]}` : \"image/jpeg\");\n\n if (image.file) {\n form.append(\"image\", image.file, filename);\n } else if (image.uri.startsWith(\"blob:\") || image.uri.startsWith(\"data:\")) {\n const blob = await fetch(image.uri).then((r) => r.blob());\n form.append(\"image\", blob, filename);\n } else {\n // React Native FormData file shape\n form.append(\"image\", {\n uri: image.uri,\n name: filename,\n type,\n } as unknown as Blob);\n }\n return http.postForm<{ message: ChatMessage }>(path, form);\n }\n return http.postJson<{ message: ChatMessage }>(path, { body });\n}\n\nexport async function markThreadRead(\n http: MessengerHttp,\n threadId: number\n): Promise<ApiResult<{ success: boolean }>> {\n return http.patchJson(`/api/messages/threads/${threadId}/read`, {});\n}\n\nexport function sumUnread(threads: MessageThread[]): number {\n return threads.reduce((sum, th) => sum + Number(th.unread_count ?? 0), 0);\n}\n","export const messengerKeys = {\n all: [\"messenger\"] as const,\n threads: () => [...messengerKeys.all, \"threads\"] as const,\n thread: (id: number) => [...messengerKeys.all, \"thread\", id] as const,\n};\n","import { useQuery } from \"@tanstack/react-query\";\nimport { listThreads } from \"../api\";\nimport { messengerKeys } from \"../queryKeys\";\nimport { useMessengerConfig } from \"../provider\";\n\nexport function useThreads(options?: { enabled?: boolean }) {\n const { http, enabled: featureOn } = useMessengerConfig();\n const enabled = (options?.enabled ?? true) && featureOn;\n\n return useQuery({\n queryKey: messengerKeys.threads(),\n queryFn: async () => {\n const res = await listThreads(http);\n if (!res.success) {\n throw new Error(res.message ?? \"Failed to load threads\");\n }\n return res.data;\n },\n enabled,\n });\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { openThread } from \"../api\";\nimport { messengerKeys } from \"../queryKeys\";\nimport { useMessengerConfig } from \"../provider\";\nimport type { MessageThread } from \"../types\";\n\nexport function useOpenThread() {\n const { http, navigation } = useMessengerConfig();\n const qc = useQueryClient();\n\n return useMutation({\n mutationFn: async (clientUserId?: number) => {\n const res = await openThread(http, clientUserId);\n if (!res.success || !res.data?.thread?.id) {\n throw new Error(res.message ?? \"Could not open thread\");\n }\n return res.data.thread as MessageThread;\n },\n onSuccess: (thread: MessageThread) => {\n void qc.invalidateQueries({ queryKey: messengerKeys.threads() });\n navigation.openThread(thread.id);\n },\n });\n}\n","/** Stable i18n keys + English fallbacks used by the package UI. */\nexport const MessengerI18n = {\n off: {\n key: \"mobile.messenger.off\",\n fallback: \"Messaging is not enabled for this account.\",\n },\n inbox: { key: \"mobile.messenger.inbox\", fallback: \"Chat\" },\n chat: { key: \"mobile.messenger.chat\", fallback: \"Chat\" },\n /** Dock / list title — prefer over inbox for web UI copy. */\n messages: { key: \"mobile.messenger.messages\", fallback: \"Chat\" },\n messagesHint: {\n key: \"mobile.messenger.messagesHint\",\n fallback: \"Message your coach anytime\",\n },\n messageCoach: {\n key: \"mobile.messenger.messageCoach\",\n fallback: \"Message your coach\",\n },\n empty: {\n key: \"mobile.messenger.empty\",\n fallback: \"No conversations yet\",\n },\n yourCoach: {\n key: \"mobile.messenger.yourCoach\",\n fallback: \"Your coach\",\n },\n photo: { key: \"mobile.messenger.photo\", fallback: \"Photo\" },\n noMessages: {\n key: \"mobile.messenger.noMessages\",\n fallback: \"No messages yet\",\n },\n startConversation: {\n key: \"mobile.messenger.startConversation\",\n fallback: \"Say hello — send the first message.\",\n },\n typeMessage: {\n key: \"mobile.messenger.typeMessage\",\n fallback: \"Type a message…\",\n },\n client: { key: \"mobile.trainer.client\", fallback: \"Client\" },\n back: { key: \"common.back\", fallback: \"Back\" },\n} as const;\n","import React from \"react\";\nimport {\n View,\n Text,\n TouchableOpacity,\n ActivityIndicator,\n ScrollView,\n RefreshControl,\n} from \"react-native\";\nimport { useMessengerConfig } from \"../provider\";\nimport { useThreads } from \"../hooks/useThreads\";\nimport { useOpenThread } from \"../hooks/useOpenThread\";\nimport { MessengerI18n } from \"../i18nKeys\";\nimport type { MessageThread } from \"../types\";\n\nfunction FeatureOff() {\n const { t, theme, navigation, onFeatureOff } = useMessengerConfig();\n if (onFeatureOff) return <>{onFeatureOff()}</>;\n const { colors, accentColor } = theme;\n return (\n <View\n style={{\n flex: 1,\n backgroundColor: colors.background,\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: 24,\n }}\n >\n <Text style={{ color: colors.textMuted, textAlign: \"center\" }}>\n {t(MessengerI18n.off.key, MessengerI18n.off.fallback)}\n </Text>\n <TouchableOpacity onPress={navigation.goBack} style={{ marginTop: 16 }}>\n <Text style={{ color: accentColor }}>\n {t(MessengerI18n.back.key, MessengerI18n.back.fallback)}\n </Text>\n </TouchableOpacity>\n </View>\n );\n}\n\nfunction ThreadRow({ thread }: { thread: MessageThread }) {\n const { user, t, isRtl, theme, navigation } = useMessengerConfig();\n const { colors, accentColor, fonts } = theme;\n const unread = Number(thread.unread_count ?? 0);\n\n return (\n <TouchableOpacity\n onPress={() => navigation.openThread(thread.id)}\n activeOpacity={0.8}\n >\n <View\n style={{\n marginBottom: 10,\n padding: 14,\n borderRadius: 14,\n backgroundColor: colors.surface,\n borderWidth: 1,\n borderColor: colors.border,\n }}\n >\n <View\n style={{\n flexDirection: isRtl ? \"row-reverse\" : \"row\",\n alignItems: \"center\",\n gap: 12,\n }}\n >\n <View style={{ flex: 1 }}>\n <Text\n style={{\n color: colors.text,\n fontFamily: fonts.displaySemiBold,\n fontWeight: \"600\",\n fontSize: 16,\n }}\n >\n {user?.role === \"admin\"\n ? thread.client_name ??\n t(MessengerI18n.client.key, MessengerI18n.client.fallback)\n : t(\n MessengerI18n.yourCoach.key,\n MessengerI18n.yourCoach.fallback\n )}\n </Text>\n <Text\n style={{\n color: colors.textSecondary,\n fontFamily: fonts.body,\n fontSize: 13,\n marginTop: 4,\n }}\n numberOfLines={1}\n >\n {thread.last_body ||\n (thread.last_image_url\n ? t(MessengerI18n.photo.key, MessengerI18n.photo.fallback)\n : t(\n MessengerI18n.noMessages.key,\n MessengerI18n.noMessages.fallback\n ))}\n </Text>\n </View>\n {unread > 0 && (\n <View\n style={{\n minWidth: 22,\n height: 22,\n borderRadius: 11,\n backgroundColor: accentColor,\n alignItems: \"center\",\n justifyContent: \"center\",\n paddingHorizontal: 6,\n }}\n >\n <Text\n style={{\n color: \"#FFF\",\n fontSize: 11,\n fontFamily: fonts.bodySemiBold,\n fontWeight: \"600\",\n }}\n >\n {unread}\n </Text>\n </View>\n )}\n </View>\n </View>\n </TouchableOpacity>\n );\n}\n\nexport function InboxScreen() {\n const { enabled, user, t, isRtl, theme, navigation } = useMessengerConfig();\n const { colors, accentColor, fonts } = theme;\n const threadsQuery = useThreads();\n const openThread = useOpenThread();\n\n if (!enabled) return <FeatureOff />;\n\n const threads = threadsQuery.data ?? [];\n const loading = threadsQuery.isLoading && threads.length === 0;\n\n return (\n <View style={{ flex: 1, backgroundColor: colors.background }}>\n <View\n style={{\n paddingTop: 56,\n paddingHorizontal: 16,\n paddingBottom: 12,\n flexDirection: isRtl ? \"row-reverse\" : \"row\",\n alignItems: \"center\",\n gap: 12,\n }}\n >\n <TouchableOpacity onPress={navigation.goBack} hitSlop={12}>\n <Text style={{ fontSize: 22, color: colors.text }}>\n {isRtl ? \"→\" : \"←\"}\n </Text>\n </TouchableOpacity>\n <Text\n style={{\n color: colors.text,\n fontSize: 22,\n fontFamily: fonts.displayBold,\n fontWeight: \"700\",\n flex: 1,\n }}\n >\n {t(MessengerI18n.inbox.key, MessengerI18n.inbox.fallback)}\n </Text>\n </View>\n\n <ScrollView\n contentContainerStyle={{ paddingHorizontal: 16, paddingBottom: 32 }}\n refreshControl={\n <RefreshControl\n refreshing={threadsQuery.isRefetching}\n onRefresh={() => void threadsQuery.refetch()}\n tintColor={accentColor}\n />\n }\n >\n {user?.role === \"client\" && threads.length === 0 && (\n <TouchableOpacity\n onPress={() => openThread.mutate(undefined)}\n disabled={openThread.isPending}\n style={{\n marginBottom: 14,\n paddingVertical: 14,\n borderRadius: 12,\n backgroundColor: accentColor,\n alignItems: \"center\",\n }}\n >\n {openThread.isPending ? (\n <ActivityIndicator color=\"#FFF\" />\n ) : (\n <Text\n style={{\n color: \"#FFF\",\n fontFamily: fonts.bodySemiBold,\n fontWeight: \"600\",\n }}\n >\n {t(\n MessengerI18n.messageCoach.key,\n MessengerI18n.messageCoach.fallback\n )}\n </Text>\n )}\n </TouchableOpacity>\n )}\n\n {loading ? (\n <ActivityIndicator color={accentColor} style={{ marginTop: 40 }} />\n ) : threads.length === 0 ? (\n <View\n style={{\n alignItems: \"center\",\n paddingVertical: 40,\n borderRadius: 14,\n backgroundColor: colors.surface,\n borderWidth: 1,\n borderColor: colors.border,\n }}\n >\n <Text style={{ fontSize: 28, color: colors.textMuted }}>···</Text>\n <Text\n style={{\n color: colors.textMuted,\n marginTop: 12,\n fontFamily: fonts.body,\n textAlign: \"center\",\n }}\n >\n {t(MessengerI18n.empty.key, MessengerI18n.empty.fallback)}\n </Text>\n </View>\n ) : (\n threads.map((th: MessageThread) => (\n <ThreadRow key={th.id} thread={th} />\n ))\n )}\n </ScrollView>\n </View>\n );\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport { getThread } from \"../api\";\nimport { messengerKeys } from \"../queryKeys\";\nimport { useMessengerConfig } from \"../provider\";\n\nconst POLL_MS = 18_000;\n\nexport function useThread(\n threadId: number,\n options?: { enabled?: boolean; poll?: boolean }\n) {\n const { http, enabled: featureOn } = useMessengerConfig();\n const enabled =\n (options?.enabled ?? true) && featureOn && Number.isFinite(threadId) && threadId > 0;\n const poll = options?.poll ?? true;\n\n return useQuery({\n queryKey: messengerKeys.thread(threadId),\n queryFn: async () => {\n const res = await getThread(http, threadId);\n if (!res.success) {\n throw new Error(res.message ?? \"Failed to load thread\");\n }\n return res.data;\n },\n enabled,\n refetchInterval: enabled && poll ? POLL_MS : false,\n });\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { sendMessage } from \"../api\";\nimport { messengerKeys } from \"../queryKeys\";\nimport { useMessengerConfig } from \"../provider\";\nimport type { ChatMessage, PickedImage } from \"../types\";\n\nexport function useSendMessage(threadId: number) {\n const { http } = useMessengerConfig();\n const qc = useQueryClient();\n\n return useMutation({\n mutationFn: async (input: { body: string; image?: PickedImage | null }) => {\n const res = await sendMessage(http, threadId, input.body, input.image);\n if (!res.success || !res.data?.message) {\n throw new Error(res.message ?? \"Send failed\");\n }\n return res.data.message as ChatMessage;\n },\n onSuccess: (message: ChatMessage) => {\n qc.setQueryData(\n messengerKeys.thread(threadId),\n (prev: { thread: unknown; messages: ChatMessage[] } | undefined) => {\n if (!prev) return prev;\n if (prev.messages.some((m) => m.id === message.id)) return prev;\n return { ...prev, messages: [...prev.messages, message] };\n }\n );\n void qc.invalidateQueries({ queryKey: messengerKeys.threads() });\n },\n });\n}\n","import React from \"react\";\nimport { View, Text, Image } from \"react-native\";\nimport type { ChatMessage } from \"../types\";\nimport { useMessengerConfig } from \"../provider\";\n\nexport function MessageBubble({ message }: { message: ChatMessage }) {\n const { user, isRtl, theme } = useMessengerConfig();\n const { colors, accentColor, fonts } = theme;\n const mine = message.sender_user_id === user?.id;\n\n return (\n <View\n style={{\n alignSelf: mine\n ? isRtl\n ? \"flex-start\"\n : \"flex-end\"\n : isRtl\n ? \"flex-end\"\n : \"flex-start\",\n maxWidth: \"80%\",\n marginBottom: 10,\n backgroundColor: mine ? accentColor : colors.surfaceSecondary,\n borderRadius: 16,\n paddingHorizontal: 12,\n paddingVertical: 10,\n }}\n >\n {message.image_url ? (\n <Image\n source={{ uri: message.image_url }}\n style={{\n width: 180,\n height: 180,\n borderRadius: 10,\n marginBottom: message.body ? 8 : 0,\n }}\n />\n ) : null}\n {message.body ? (\n <Text\n style={{\n color: mine ? \"#FFF\" : colors.text,\n fontFamily: fonts.body,\n fontSize: 15,\n }}\n >\n {message.body}\n </Text>\n ) : null}\n </View>\n );\n}\n","import React, { useState } from \"react\";\nimport {\n View,\n Text,\n TextInput,\n TouchableOpacity,\n ActivityIndicator,\n Platform,\n} from \"react-native\";\nimport { useMessengerConfig } from \"../provider\";\nimport { MessengerI18n } from \"../i18nKeys\";\nimport type { PickedImage } from \"../types\";\n\nexport function Composer({\n sending,\n onSend,\n}: {\n sending: boolean;\n onSend: (body: string, image?: PickedImage | null) => void | Promise<void>;\n}) {\n const { t, isRtl, theme, pickImage } = useMessengerConfig();\n const { colors, accentColor, fonts } = theme;\n const [body, setBody] = useState(\"\");\n\n async function onPick() {\n const image = await pickImage();\n if (image) {\n await onSend(body, image);\n setBody(\"\");\n }\n }\n\n async function onPressSend() {\n if (!body.trim() || sending) return;\n const text = body;\n await onSend(text, null);\n setBody(\"\");\n }\n\n return (\n <View\n style={{\n flexDirection: isRtl ? \"row-reverse\" : \"row\",\n alignItems: \"flex-end\",\n gap: 8,\n paddingHorizontal: 12,\n paddingVertical: 10,\n borderTopWidth: 1,\n borderTopColor: colors.border,\n paddingBottom: Platform.OS === \"ios\" ? 28 : 12,\n }}\n >\n <TouchableOpacity onPress={onPick} hitSlop={8} disabled={sending}>\n <Text style={{ fontSize: 22, color: accentColor }}>▣</Text>\n </TouchableOpacity>\n <TextInput\n value={body}\n onChangeText={setBody}\n placeholder={t(\n MessengerI18n.typeMessage.key,\n MessengerI18n.typeMessage.fallback\n )}\n placeholderTextColor={colors.textMuted}\n multiline\n style={{\n flex: 1,\n maxHeight: 100,\n borderWidth: 1,\n borderColor: colors.border,\n borderRadius: 16,\n paddingHorizontal: 14,\n paddingVertical: 10,\n color: colors.text,\n fontFamily: fonts.body,\n textAlign: isRtl ? \"right\" : \"left\",\n backgroundColor: colors.surface,\n }}\n />\n <TouchableOpacity\n onPress={onPressSend}\n disabled={sending || !body.trim()}\n style={{\n width: 40,\n height: 40,\n borderRadius: 20,\n backgroundColor: body.trim()\n ? accentColor\n : colors.surfaceSecondary,\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n >\n {sending ? (\n <ActivityIndicator color=\"#FFF\" size=\"small\" />\n ) : (\n <Text\n style={{\n color: body.trim() ? \"#FFF\" : colors.textMuted,\n fontSize: 16,\n fontWeight: \"700\",\n }}\n >\n ➤\n </Text>\n )}\n </TouchableOpacity>\n </View>\n );\n}\n","import React, { useRef } from \"react\";\nimport {\n View,\n Text,\n TouchableOpacity,\n ActivityIndicator,\n FlatList,\n KeyboardAvoidingView,\n Platform,\n} from \"react-native\";\nimport { useMessengerConfig } from \"../provider\";\nimport { useThread } from \"../hooks/useThread\";\nimport { useSendMessage } from \"../hooks/useSendMessage\";\nimport { MessageBubble } from \"./MessageBubble\";\nimport { Composer } from \"./Composer\";\nimport { MessengerI18n } from \"../i18nKeys\";\nimport type { ChatMessage, PickedImage } from \"../types\";\n\nfunction FeatureOff() {\n const { t, theme, onFeatureOff } = useMessengerConfig();\n if (onFeatureOff) return <>{onFeatureOff()}</>;\n return (\n <View\n style={{\n flex: 1,\n backgroundColor: theme.colors.background,\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n >\n <Text style={{ color: theme.colors.textMuted }}>\n {t(MessengerI18n.off.key, MessengerI18n.off.fallback)}\n </Text>\n </View>\n );\n}\n\nexport function ThreadScreen({ threadId }: { threadId: number }) {\n const { enabled, t, isRtl, theme, navigation } = useMessengerConfig();\n const { colors, accentColor, fonts } = theme;\n const listRef = useRef<FlatList<ChatMessage> | null>(null);\n const threadQuery = useThread(threadId);\n const sendMutation = useSendMessage(threadId);\n\n if (!enabled) return <FeatureOff />;\n\n const messages = threadQuery.data?.messages ?? [];\n const loading = threadQuery.isLoading && messages.length === 0;\n\n async function handleSend(body: string, image?: PickedImage | null) {\n if ((!body.trim() && !image) || sendMutation.isPending) return;\n await sendMutation.mutateAsync({ body, image });\n setTimeout(() => listRef.current?.scrollToEnd({ animated: true }), 100);\n }\n\n return (\n <KeyboardAvoidingView\n style={{ flex: 1, backgroundColor: colors.background }}\n behavior={Platform.OS === \"ios\" ? \"padding\" : undefined}\n keyboardVerticalOffset={0}\n >\n <View\n style={{\n paddingTop: 56,\n paddingHorizontal: 16,\n paddingBottom: 12,\n flexDirection: isRtl ? \"row-reverse\" : \"row\",\n alignItems: \"center\",\n gap: 12,\n borderBottomWidth: 1,\n borderBottomColor: colors.border,\n }}\n >\n <TouchableOpacity onPress={navigation.goBack} hitSlop={12}>\n <Text style={{ fontSize: 22, color: colors.text }}>\n {isRtl ? \"→\" : \"←\"}\n </Text>\n </TouchableOpacity>\n <Text\n style={{\n color: colors.text,\n fontSize: 18,\n fontFamily: fonts.displayBold,\n fontWeight: \"700\",\n flex: 1,\n }}\n >\n {t(MessengerI18n.chat.key, MessengerI18n.chat.fallback)}\n </Text>\n </View>\n\n {loading ? (\n <ActivityIndicator color={accentColor} style={{ marginTop: 40 }} />\n ) : (\n <FlatList\n ref={listRef}\n data={messages}\n keyExtractor={(m: ChatMessage) => String(m.id)}\n contentContainerStyle={{ padding: 16, paddingBottom: 8 }}\n onContentSizeChange={() =>\n listRef.current?.scrollToEnd({ animated: false })\n }\n ListEmptyComponent={\n <Text\n style={{\n color: colors.textMuted,\n textAlign: \"center\",\n marginTop: 40,\n fontFamily: fonts.body,\n }}\n >\n {t(\n MessengerI18n.startConversation.key,\n MessengerI18n.startConversation.fallback\n )}\n </Text>\n }\n renderItem={({ item }: { item: ChatMessage }) => (\n <MessageBubble message={item} />\n )}\n />\n )}\n\n <Composer sending={sendMutation.isPending} onSend={handleSend} />\n </KeyboardAvoidingView>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/native/InboxScreen.tsx","../../src/native/MessageBubble.tsx","../../src/native/Composer.tsx","../../src/native/ThreadScreen.tsx"],"names":["jsxs","View","jsx","Text","TouchableOpacity","ActivityIndicator","FeatureOff","Fragment","Platform"],"mappings":"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","file":"index.js","sourcesContent":["import React from \"react\";\nimport {\n View,\n Text,\n TouchableOpacity,\n ActivityIndicator,\n ScrollView,\n RefreshControl,\n} from \"react-native\";\nimport { useMessengerConfig } from \"../provider\";\nimport { useThreads } from \"../hooks/useThreads\";\nimport { useOpenThread } from \"../hooks/useOpenThread\";\nimport { MessengerI18n } from \"../i18nKeys\";\nimport type { MessageThread } from \"../types\";\n\nfunction FeatureOff() {\n const { t, theme, navigation, onFeatureOff } = useMessengerConfig();\n if (onFeatureOff) return <>{onFeatureOff()}</>;\n const { colors, accentColor } = theme;\n return (\n <View\n style={{\n flex: 1,\n backgroundColor: colors.background,\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: 24,\n }}\n >\n <Text style={{ color: colors.textMuted, textAlign: \"center\" }}>\n {t(MessengerI18n.off.key, MessengerI18n.off.fallback)}\n </Text>\n <TouchableOpacity onPress={navigation.goBack} style={{ marginTop: 16 }}>\n <Text style={{ color: accentColor }}>\n {t(MessengerI18n.back.key, MessengerI18n.back.fallback)}\n </Text>\n </TouchableOpacity>\n </View>\n );\n}\n\nfunction ThreadRow({ thread }: { thread: MessageThread }) {\n const { user, t, isRtl, theme, navigation } = useMessengerConfig();\n const { colors, accentColor, fonts } = theme;\n const unread = Number(thread.unread_count ?? 0);\n\n return (\n <TouchableOpacity\n onPress={() => navigation.openThread(thread.id)}\n activeOpacity={0.8}\n >\n <View\n style={{\n marginBottom: 10,\n padding: 14,\n borderRadius: 14,\n backgroundColor: colors.surface,\n borderWidth: 1,\n borderColor: colors.border,\n }}\n >\n <View\n style={{\n flexDirection: isRtl ? \"row-reverse\" : \"row\",\n alignItems: \"center\",\n gap: 12,\n }}\n >\n <View style={{ flex: 1 }}>\n <Text\n style={{\n color: colors.text,\n fontFamily: fonts.displaySemiBold,\n fontWeight: \"600\",\n fontSize: 16,\n }}\n >\n {user?.role === \"admin\"\n ? thread.client_name ??\n t(MessengerI18n.client.key, MessengerI18n.client.fallback)\n : t(\n MessengerI18n.yourCoach.key,\n MessengerI18n.yourCoach.fallback\n )}\n </Text>\n <Text\n style={{\n color: colors.textSecondary,\n fontFamily: fonts.body,\n fontSize: 13,\n marginTop: 4,\n }}\n numberOfLines={1}\n >\n {thread.last_body ||\n (thread.last_image_url\n ? t(MessengerI18n.photo.key, MessengerI18n.photo.fallback)\n : t(\n MessengerI18n.noMessages.key,\n MessengerI18n.noMessages.fallback\n ))}\n </Text>\n </View>\n {unread > 0 && (\n <View\n style={{\n minWidth: 22,\n height: 22,\n borderRadius: 11,\n backgroundColor: accentColor,\n alignItems: \"center\",\n justifyContent: \"center\",\n paddingHorizontal: 6,\n }}\n >\n <Text\n style={{\n color: \"#FFF\",\n fontSize: 11,\n fontFamily: fonts.bodySemiBold,\n fontWeight: \"600\",\n }}\n >\n {unread}\n </Text>\n </View>\n )}\n </View>\n </View>\n </TouchableOpacity>\n );\n}\n\nexport function InboxScreen() {\n const { enabled, user, t, isRtl, theme, navigation } = useMessengerConfig();\n const { colors, accentColor, fonts } = theme;\n const threadsQuery = useThreads();\n const openThread = useOpenThread();\n\n if (!enabled) return <FeatureOff />;\n\n const threads = threadsQuery.data ?? [];\n const loading = threadsQuery.isLoading && threads.length === 0;\n\n return (\n <View style={{ flex: 1, backgroundColor: colors.background }}>\n <View\n style={{\n paddingTop: 56,\n paddingHorizontal: 16,\n paddingBottom: 12,\n flexDirection: isRtl ? \"row-reverse\" : \"row\",\n alignItems: \"center\",\n gap: 12,\n }}\n >\n <TouchableOpacity onPress={navigation.goBack} hitSlop={12}>\n <Text style={{ fontSize: 22, color: colors.text }}>\n {isRtl ? \"→\" : \"←\"}\n </Text>\n </TouchableOpacity>\n <Text\n style={{\n color: colors.text,\n fontSize: 22,\n fontFamily: fonts.displayBold,\n fontWeight: \"700\",\n flex: 1,\n }}\n >\n {t(MessengerI18n.inbox.key, MessengerI18n.inbox.fallback)}\n </Text>\n </View>\n\n <ScrollView\n contentContainerStyle={{ paddingHorizontal: 16, paddingBottom: 32 }}\n refreshControl={\n <RefreshControl\n refreshing={threadsQuery.isRefetching}\n onRefresh={() => void threadsQuery.refetch()}\n tintColor={accentColor}\n />\n }\n >\n {user?.role === \"client\" && threads.length === 0 && (\n <TouchableOpacity\n onPress={() => openThread.mutate(undefined)}\n disabled={openThread.isPending}\n style={{\n marginBottom: 14,\n paddingVertical: 14,\n borderRadius: 12,\n backgroundColor: accentColor,\n alignItems: \"center\",\n }}\n >\n {openThread.isPending ? (\n <ActivityIndicator color=\"#FFF\" />\n ) : (\n <Text\n style={{\n color: \"#FFF\",\n fontFamily: fonts.bodySemiBold,\n fontWeight: \"600\",\n }}\n >\n {t(\n MessengerI18n.messageCoach.key,\n MessengerI18n.messageCoach.fallback\n )}\n </Text>\n )}\n </TouchableOpacity>\n )}\n\n {loading ? (\n <ActivityIndicator color={accentColor} style={{ marginTop: 40 }} />\n ) : threads.length === 0 ? (\n <View\n style={{\n alignItems: \"center\",\n paddingVertical: 40,\n borderRadius: 14,\n backgroundColor: colors.surface,\n borderWidth: 1,\n borderColor: colors.border,\n }}\n >\n <Text style={{ fontSize: 28, color: colors.textMuted }}>···</Text>\n <Text\n style={{\n color: colors.textMuted,\n marginTop: 12,\n fontFamily: fonts.body,\n textAlign: \"center\",\n }}\n >\n {t(MessengerI18n.empty.key, MessengerI18n.empty.fallback)}\n </Text>\n </View>\n ) : (\n threads.map((th: MessageThread) => (\n <ThreadRow key={th.id} thread={th} />\n ))\n )}\n </ScrollView>\n </View>\n );\n}\n","import React from \"react\";\nimport { View, Text, Image } from \"react-native\";\nimport type { ChatMessage } from \"../types\";\nimport { useMessengerConfig } from \"../provider\";\n\nexport function MessageBubble({ message }: { message: ChatMessage }) {\n const { user, isRtl, theme } = useMessengerConfig();\n const { colors, accentColor, fonts } = theme;\n const mine = message.sender_user_id === user?.id;\n\n return (\n <View\n style={{\n alignSelf: mine\n ? isRtl\n ? \"flex-start\"\n : \"flex-end\"\n : isRtl\n ? \"flex-end\"\n : \"flex-start\",\n maxWidth: \"80%\",\n marginBottom: 10,\n backgroundColor: mine ? accentColor : colors.surfaceSecondary,\n borderRadius: 16,\n paddingHorizontal: 12,\n paddingVertical: 10,\n }}\n >\n {message.image_url ? (\n <Image\n source={{ uri: message.image_url }}\n style={{\n width: 180,\n height: 180,\n borderRadius: 10,\n marginBottom: message.body ? 8 : 0,\n }}\n />\n ) : null}\n {message.body ? (\n <Text\n style={{\n color: mine ? \"#FFF\" : colors.text,\n fontFamily: fonts.body,\n fontSize: 15,\n }}\n >\n {message.body}\n </Text>\n ) : null}\n </View>\n );\n}\n","import React, { useState } from \"react\";\nimport {\n View,\n Text,\n TextInput,\n TouchableOpacity,\n ActivityIndicator,\n Platform,\n} from \"react-native\";\nimport { useMessengerConfig } from \"../provider\";\nimport { MessengerI18n } from \"../i18nKeys\";\nimport type { PickedImage } from \"../types\";\n\nexport function Composer({\n sending,\n onSend,\n}: {\n sending: boolean;\n onSend: (body: string, image?: PickedImage | null) => void | Promise<void>;\n}) {\n const { t, isRtl, theme, pickImage } = useMessengerConfig();\n const { colors, accentColor, fonts } = theme;\n const [body, setBody] = useState(\"\");\n\n async function onPick() {\n const image = await pickImage();\n if (image) {\n await onSend(body, image);\n setBody(\"\");\n }\n }\n\n async function onPressSend() {\n if (!body.trim() || sending) return;\n const text = body;\n await onSend(text, null);\n setBody(\"\");\n }\n\n return (\n <View\n style={{\n flexDirection: isRtl ? \"row-reverse\" : \"row\",\n alignItems: \"flex-end\",\n gap: 8,\n paddingHorizontal: 12,\n paddingVertical: 10,\n borderTopWidth: 1,\n borderTopColor: colors.border,\n paddingBottom: Platform.OS === \"ios\" ? 28 : 12,\n }}\n >\n <TouchableOpacity onPress={onPick} hitSlop={8} disabled={sending}>\n <Text style={{ fontSize: 22, color: accentColor }}>▣</Text>\n </TouchableOpacity>\n <TextInput\n value={body}\n onChangeText={setBody}\n placeholder={t(\n MessengerI18n.typeMessage.key,\n MessengerI18n.typeMessage.fallback\n )}\n placeholderTextColor={colors.textMuted}\n multiline\n style={{\n flex: 1,\n maxHeight: 100,\n borderWidth: 1,\n borderColor: colors.border,\n borderRadius: 16,\n paddingHorizontal: 14,\n paddingVertical: 10,\n color: colors.text,\n fontFamily: fonts.body,\n textAlign: isRtl ? \"right\" : \"left\",\n backgroundColor: colors.surface,\n }}\n />\n <TouchableOpacity\n onPress={onPressSend}\n disabled={sending || !body.trim()}\n style={{\n width: 40,\n height: 40,\n borderRadius: 20,\n backgroundColor: body.trim()\n ? accentColor\n : colors.surfaceSecondary,\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n >\n {sending ? (\n <ActivityIndicator color=\"#FFF\" size=\"small\" />\n ) : (\n <Text\n style={{\n color: body.trim() ? \"#FFF\" : colors.textMuted,\n fontSize: 16,\n fontWeight: \"700\",\n }}\n >\n ➤\n </Text>\n )}\n </TouchableOpacity>\n </View>\n );\n}\n","import React, { useRef } from \"react\";\nimport {\n View,\n Text,\n TouchableOpacity,\n ActivityIndicator,\n FlatList,\n KeyboardAvoidingView,\n Platform,\n} from \"react-native\";\nimport { useMessengerConfig } from \"../provider\";\nimport { useThread } from \"../hooks/useThread\";\nimport { useSendMessage } from \"../hooks/useSendMessage\";\nimport { MessageBubble } from \"./MessageBubble\";\nimport { Composer } from \"./Composer\";\nimport { MessengerI18n } from \"../i18nKeys\";\nimport type { ChatMessage, PickedImage } from \"../types\";\n\nfunction FeatureOff() {\n const { t, theme, onFeatureOff } = useMessengerConfig();\n if (onFeatureOff) return <>{onFeatureOff()}</>;\n return (\n <View\n style={{\n flex: 1,\n backgroundColor: theme.colors.background,\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n >\n <Text style={{ color: theme.colors.textMuted }}>\n {t(MessengerI18n.off.key, MessengerI18n.off.fallback)}\n </Text>\n </View>\n );\n}\n\nexport function ThreadScreen({ threadId }: { threadId: number }) {\n const { enabled, t, isRtl, theme, navigation } = useMessengerConfig();\n const { colors, accentColor, fonts } = theme;\n const listRef = useRef<FlatList<ChatMessage> | null>(null);\n const threadQuery = useThread(threadId);\n const sendMutation = useSendMessage(threadId);\n\n if (!enabled) return <FeatureOff />;\n\n const messages = threadQuery.data?.messages ?? [];\n const loading = threadQuery.isLoading && messages.length === 0;\n\n async function handleSend(body: string, image?: PickedImage | null) {\n if ((!body.trim() && !image) || sendMutation.isPending) return;\n await sendMutation.mutateAsync({ body, image });\n setTimeout(() => listRef.current?.scrollToEnd({ animated: true }), 100);\n }\n\n return (\n <KeyboardAvoidingView\n style={{ flex: 1, backgroundColor: colors.background }}\n behavior={Platform.OS === \"ios\" ? \"padding\" : undefined}\n keyboardVerticalOffset={0}\n >\n <View\n style={{\n paddingTop: 56,\n paddingHorizontal: 16,\n paddingBottom: 12,\n flexDirection: isRtl ? \"row-reverse\" : \"row\",\n alignItems: \"center\",\n gap: 12,\n borderBottomWidth: 1,\n borderBottomColor: colors.border,\n }}\n >\n <TouchableOpacity onPress={navigation.goBack} hitSlop={12}>\n <Text style={{ fontSize: 22, color: colors.text }}>\n {isRtl ? \"→\" : \"←\"}\n </Text>\n </TouchableOpacity>\n <Text\n style={{\n color: colors.text,\n fontSize: 18,\n fontFamily: fonts.displayBold,\n fontWeight: \"700\",\n flex: 1,\n }}\n >\n {t(MessengerI18n.chat.key, MessengerI18n.chat.fallback)}\n </Text>\n </View>\n\n {loading ? (\n <ActivityIndicator color={accentColor} style={{ marginTop: 40 }} />\n ) : (\n <FlatList\n ref={listRef}\n data={messages}\n keyExtractor={(m: ChatMessage) => String(m.id)}\n contentContainerStyle={{ padding: 16, paddingBottom: 8 }}\n onContentSizeChange={() =>\n listRef.current?.scrollToEnd({ animated: false })\n }\n ListEmptyComponent={\n <Text\n style={{\n color: colors.textMuted,\n textAlign: \"center\",\n marginTop: 40,\n fontFamily: fonts.body,\n }}\n >\n {t(\n MessengerI18n.startConversation.key,\n MessengerI18n.startConversation.fallback\n )}\n </Text>\n }\n renderItem={({ item }: { item: ChatMessage }) => (\n <MessageBubble message={item} />\n )}\n />\n )}\n\n <Composer sending={sendMutation.isPending} onSend={handleSend} />\n </KeyboardAvoidingView>\n );\n}\n"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
import { b as MessengerConfig } from './types-B7dU_l7c.cjs';
|
|
3
|
+
|
|
4
|
+
declare function MessengerProvider({ config, children, }: {
|
|
5
|
+
config: MessengerConfig;
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
}): React.JSX.Element;
|
|
8
|
+
declare function useMessengerConfig(): MessengerConfig;
|
|
9
|
+
/** Safe variant for optional host chrome (returns null outside provider). */
|
|
10
|
+
declare function useOptionalMessengerConfig(): MessengerConfig | null;
|
|
11
|
+
|
|
12
|
+
interface MessengerUiState {
|
|
13
|
+
open: boolean;
|
|
14
|
+
threadId: number | null;
|
|
15
|
+
openInbox: () => void;
|
|
16
|
+
openThread: (threadId: number) => void;
|
|
17
|
+
close: () => void;
|
|
18
|
+
setOpen: (open: boolean) => void;
|
|
19
|
+
}
|
|
20
|
+
declare function MessengerUiProvider({ children }: {
|
|
21
|
+
children: ReactNode;
|
|
22
|
+
}): React.JSX.Element;
|
|
23
|
+
declare function useMessengerUi(): MessengerUiState;
|
|
24
|
+
declare function useOptionalMessengerUi(): MessengerUiState | null;
|
|
25
|
+
|
|
26
|
+
export { MessengerProvider as M, MessengerUiProvider as a, useMessengerUi as b, useOptionalMessengerConfig as c, useOptionalMessengerUi as d, useMessengerConfig as u };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
import { b as MessengerConfig } from './types-B7dU_l7c.js';
|
|
3
|
+
|
|
4
|
+
declare function MessengerProvider({ config, children, }: {
|
|
5
|
+
config: MessengerConfig;
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
}): React.JSX.Element;
|
|
8
|
+
declare function useMessengerConfig(): MessengerConfig;
|
|
9
|
+
/** Safe variant for optional host chrome (returns null outside provider). */
|
|
10
|
+
declare function useOptionalMessengerConfig(): MessengerConfig | null;
|
|
11
|
+
|
|
12
|
+
interface MessengerUiState {
|
|
13
|
+
open: boolean;
|
|
14
|
+
threadId: number | null;
|
|
15
|
+
openInbox: () => void;
|
|
16
|
+
openThread: (threadId: number) => void;
|
|
17
|
+
close: () => void;
|
|
18
|
+
setOpen: (open: boolean) => void;
|
|
19
|
+
}
|
|
20
|
+
declare function MessengerUiProvider({ children }: {
|
|
21
|
+
children: ReactNode;
|
|
22
|
+
}): React.JSX.Element;
|
|
23
|
+
declare function useMessengerUi(): MessengerUiState;
|
|
24
|
+
declare function useOptionalMessengerUi(): MessengerUiState | null;
|
|
25
|
+
|
|
26
|
+
export { MessengerProvider as M, MessengerUiProvider as a, useMessengerUi as b, useOptionalMessengerConfig as c, useOptionalMessengerUi as d, useMessengerConfig as u };
|