@ethora/chat-component-rn 26.8.3 → 26.8.5
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/CHANGELOG.md +4 -0
- package/lib/commonjs/components/Header/HeaderRoomList.js +12 -7
- package/lib/commonjs/components/Header/HeaderRoomList.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ChatRoom.js +23 -3
- package/lib/commonjs/components/MainComponents/ChatRoom.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ChatWrapper.js +40 -9
- package/lib/commonjs/components/MainComponents/ChatWrapper.js.map +1 -1
- package/lib/commonjs/components/MainComponents/KeyboardInputDock.js +40 -0
- package/lib/commonjs/components/MainComponents/KeyboardInputDock.js.map +1 -0
- package/lib/commonjs/components/MainComponents/ReduxWrapper.js +43 -6
- package/lib/commonjs/components/MainComponents/ReduxWrapper.js.map +1 -1
- package/lib/commonjs/components/MainComponents/RoomStack.js +202 -0
- package/lib/commonjs/components/MainComponents/RoomStack.js.map +1 -0
- package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js +6 -1
- package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
- package/lib/commonjs/components/Modals/Modal/Modal.js +24 -0
- package/lib/commonjs/components/Modals/Modal/Modal.js.map +1 -1
- package/lib/commonjs/components/Modals/Modal/SwipeBackLayer.js +146 -0
- package/lib/commonjs/components/Modals/Modal/SwipeBackLayer.js.map +1 -0
- package/lib/commonjs/components/Modals/ProfileHeader/ProfileHeader.js +28 -10
- package/lib/commonjs/components/Modals/ProfileHeader/ProfileHeader.js.map +1 -1
- package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js +9 -3
- package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
- package/lib/commonjs/components/Modals/UserSettingsModal/UserSettingsModal.js +136 -3
- package/lib/commonjs/components/Modals/UserSettingsModal/UserSettingsModal.js.map +1 -1
- package/lib/commonjs/helpers/keyboardLayout.js +23 -1
- package/lib/commonjs/helpers/keyboardLayout.js.map +1 -1
- package/lib/commonjs/helpers/preferencesStorage.js +44 -0
- package/lib/commonjs/helpers/preferencesStorage.js.map +1 -0
- package/lib/commonjs/i18n/strings.js +42 -0
- package/lib/commonjs/i18n/strings.js.map +1 -1
- package/lib/commonjs/main.js +13 -0
- package/lib/commonjs/main.js.map +1 -1
- package/lib/commonjs/roomStore/chatSettingsSlice.js +17 -4
- package/lib/commonjs/roomStore/chatSettingsSlice.js.map +1 -1
- package/lib/commonjs/services/pushRegistration.js +13 -2
- package/lib/commonjs/services/pushRegistration.js.map +1 -1
- package/lib/commonjs/theme/theme.js +28 -4
- package/lib/commonjs/theme/theme.js.map +1 -1
- package/lib/commonjs/version.js +1 -1
- package/lib/module/components/Header/HeaderRoomList.js +12 -7
- package/lib/module/components/Header/HeaderRoomList.js.map +1 -1
- package/lib/module/components/MainComponents/ChatRoom.js +24 -4
- package/lib/module/components/MainComponents/ChatRoom.js.map +1 -1
- package/lib/module/components/MainComponents/ChatWrapper.js +41 -10
- package/lib/module/components/MainComponents/ChatWrapper.js.map +1 -1
- package/lib/module/components/MainComponents/KeyboardInputDock.js +33 -0
- package/lib/module/components/MainComponents/KeyboardInputDock.js.map +1 -0
- package/lib/module/components/MainComponents/ReduxWrapper.js +47 -10
- package/lib/module/components/MainComponents/ReduxWrapper.js.map +1 -1
- package/lib/module/components/MainComponents/RoomStack.js +198 -0
- package/lib/module/components/MainComponents/RoomStack.js.map +1 -0
- package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js +6 -1
- package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
- package/lib/module/components/Modals/Modal/Modal.js +25 -1
- package/lib/module/components/Modals/Modal/Modal.js.map +1 -1
- package/lib/module/components/Modals/Modal/SwipeBackLayer.js +140 -0
- package/lib/module/components/Modals/Modal/SwipeBackLayer.js.map +1 -0
- package/lib/module/components/Modals/ProfileHeader/ProfileHeader.js +29 -11
- package/lib/module/components/Modals/ProfileHeader/ProfileHeader.js.map +1 -1
- package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js +10 -4
- package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
- package/lib/module/components/Modals/UserSettingsModal/UserSettingsModal.js +139 -6
- package/lib/module/components/Modals/UserSettingsModal/UserSettingsModal.js.map +1 -1
- package/lib/module/helpers/keyboardLayout.js +20 -0
- package/lib/module/helpers/keyboardLayout.js.map +1 -1
- package/lib/module/helpers/preferencesStorage.js +36 -0
- package/lib/module/helpers/preferencesStorage.js.map +1 -0
- package/lib/module/i18n/strings.js +42 -0
- package/lib/module/i18n/strings.js.map +1 -1
- package/lib/module/main.js +1 -0
- package/lib/module/main.js.map +1 -1
- package/lib/module/roomStore/chatSettingsSlice.js +14 -3
- package/lib/module/roomStore/chatSettingsSlice.js.map +1 -1
- package/lib/module/services/pushRegistration.js +13 -2
- package/lib/module/services/pushRegistration.js.map +1 -1
- package/lib/module/theme/theme.js +28 -3
- package/lib/module/theme/theme.js.map +1 -1
- package/lib/module/version.js +1 -1
- package/lib/typescript/components/Header/HeaderRoomList.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ChatRoom.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ChatWrapper.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/KeyboardInputDock.d.ts +16 -0
- package/lib/typescript/components/MainComponents/KeyboardInputDock.d.ts.map +1 -0
- package/lib/typescript/components/MainComponents/ReduxWrapper.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/RoomStack.d.ts +37 -0
- package/lib/typescript/components/MainComponents/RoomStack.d.ts.map +1 -0
- package/lib/typescript/components/Modals/ChatProfileModal/ChatProfileModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/Modal/Modal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/Modal/SwipeBackLayer.d.ts +15 -0
- package/lib/typescript/components/Modals/Modal/SwipeBackLayer.d.ts.map +1 -0
- package/lib/typescript/components/Modals/ProfileHeader/ProfileHeader.d.ts.map +1 -1
- package/lib/typescript/components/Modals/UserProfileModal/UserProfileModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/UserSettingsModal/UserSettingsModal.d.ts.map +1 -1
- package/lib/typescript/helpers/keyboardLayout.d.ts +6 -0
- package/lib/typescript/helpers/keyboardLayout.d.ts.map +1 -1
- package/lib/typescript/helpers/preferencesStorage.d.ts +11 -0
- package/lib/typescript/helpers/preferencesStorage.d.ts.map +1 -0
- package/lib/typescript/i18n/strings.d.ts.map +1 -1
- package/lib/typescript/main.d.ts +2 -0
- package/lib/typescript/main.d.ts.map +1 -1
- package/lib/typescript/roomStore/chatSettingsSlice.d.ts +12 -1
- package/lib/typescript/roomStore/chatSettingsSlice.d.ts.map +1 -1
- package/lib/typescript/services/pushRegistration.d.ts.map +1 -1
- package/lib/typescript/theme/theme.d.ts +17 -3
- package/lib/typescript/theme/theme.d.ts.map +1 -1
- package/lib/typescript/types/types.d.ts +23 -1
- package/lib/typescript/types/types.d.ts.map +1 -1
- package/lib/typescript/version.d.ts +1 -1
- package/package.json +2 -2
- package/src/components/Header/HeaderRoomList.tsx +7 -5
- package/src/components/MainComponents/ChatRoom.tsx +29 -3
- package/src/components/MainComponents/ChatWrapper.tsx +46 -12
- package/src/components/MainComponents/KeyboardInputDock.tsx +47 -0
- package/src/components/MainComponents/ReduxWrapper.tsx +52 -11
- package/src/components/MainComponents/RoomStack.tsx +236 -0
- package/src/components/Modals/ChatProfileModal/ChatProfileModal.tsx +4 -0
- package/src/components/Modals/Modal/Modal.tsx +32 -1
- package/src/components/Modals/Modal/SwipeBackLayer.tsx +170 -0
- package/src/components/Modals/ProfileHeader/ProfileHeader.tsx +29 -8
- package/src/components/Modals/UserProfileModal/UserProfileModal.tsx +6 -3
- package/src/components/Modals/UserSettingsModal/UserSettingsModal.tsx +157 -4
- package/src/helpers/keyboardLayout.ts +26 -0
- package/src/helpers/preferencesStorage.ts +40 -0
- package/src/i18n/strings.ts +42 -0
- package/src/main.ts +2 -0
- package/src/roomStore/chatSettingsSlice.ts +24 -2
- package/src/services/pushRegistration.ts +15 -2
- package/src/theme/theme.ts +39 -5
- package/src/types/types.ts +24 -1
- package/src/version.ts +1 -1
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
import { Iso639_1Codes } from '../types/models/language.model';
|
|
13
13
|
import type { TranslateMode } from '../utils/translateModePolicy';
|
|
14
14
|
import { secureUserStorage } from '../helpers/secureUserStorage';
|
|
15
|
+
import { applyThemePreference, type ThemePreference } from '../theme/theme';
|
|
15
16
|
|
|
16
17
|
export interface ChatState {
|
|
17
18
|
user: User;
|
|
@@ -29,6 +30,14 @@ export interface ChatState {
|
|
|
29
30
|
* See utils/translateModePolicy.
|
|
30
31
|
*/
|
|
31
32
|
translateMode?: TranslateMode;
|
|
33
|
+
/**
|
|
34
|
+
* Appearance picked in Settings (light / dark / system). Persisted per
|
|
35
|
+
* device; folded into `config.dark` by setConfig / setThemePreference so
|
|
36
|
+
* every consumer of `config` sees the effective value.
|
|
37
|
+
*/
|
|
38
|
+
themePreference?: ThemePreference;
|
|
39
|
+
/** Push notifications toggle from Settings. `undefined` = on. */
|
|
40
|
+
pushEnabled?: boolean;
|
|
32
41
|
}
|
|
33
42
|
|
|
34
43
|
export const unpackAndTransform = (input?: User): User => {
|
|
@@ -126,11 +135,22 @@ const reducers = {
|
|
|
126
135
|
};
|
|
127
136
|
}
|
|
128
137
|
},
|
|
138
|
+
setThemePreference: (
|
|
139
|
+
state: WritableDraft<ChatState>,
|
|
140
|
+
action: PayloadAction<ThemePreference | undefined>
|
|
141
|
+
) => {
|
|
142
|
+
state.themePreference = action.payload;
|
|
143
|
+
state.config = applyThemePreference(state.config as IConfig | undefined, action.payload) as any;
|
|
144
|
+
},
|
|
145
|
+
setPushEnabled: (state: WritableDraft<ChatState>, action: PayloadAction<boolean>) => {
|
|
146
|
+
state.pushEnabled = action.payload;
|
|
147
|
+
},
|
|
129
148
|
setConfig: (state: WritableDraft<ChatState>, action: PayloadAction<IConfig | undefined>) => {
|
|
130
149
|
// Cast away immer's WritableDraft — IConfig contains callable
|
|
131
150
|
// fields (eventHandlers, customComponent) that confuse the draft
|
|
132
|
-
// type inference but are inert at write-time.
|
|
133
|
-
|
|
151
|
+
// type inference but are inert at write-time. The user's in-app
|
|
152
|
+
// appearance choice survives a host re-dispatch.
|
|
153
|
+
state.config = applyThemePreference(action.payload, state.themePreference) as any;
|
|
134
154
|
},
|
|
135
155
|
setActiveModal: (state: WritableDraft<ChatState>, action: PayloadAction<ModalType | undefined>) => {
|
|
136
156
|
state.activeModal = action.payload;
|
|
@@ -220,6 +240,8 @@ export const {
|
|
|
220
240
|
setStoreClient,
|
|
221
241
|
setLangSource,
|
|
222
242
|
setTranslateMode,
|
|
243
|
+
setThemePreference,
|
|
244
|
+
setPushEnabled,
|
|
223
245
|
} = chatSlice.actions;
|
|
224
246
|
|
|
225
247
|
export default chatSlice.reducer;
|
|
@@ -70,7 +70,10 @@ const readSession = (): Session => {
|
|
|
70
70
|
xmppUsername: String(user?.xmppUsername || ''),
|
|
71
71
|
projectName: String(config?.projectName || '').trim(),
|
|
72
72
|
gatewayUrl: String(config?.pushNotifications?.apiUrl || '').trim(),
|
|
73
|
-
|
|
73
|
+
// Off by config (host) or by the user's Settings toggle.
|
|
74
|
+
pushDisabled:
|
|
75
|
+
config?.pushNotifications?.enabled === false ||
|
|
76
|
+
slice?.pushEnabled === false,
|
|
74
77
|
};
|
|
75
78
|
};
|
|
76
79
|
|
|
@@ -233,7 +236,17 @@ const ensureWatching = (): void => {
|
|
|
233
236
|
hookIdentity = null;
|
|
234
237
|
return;
|
|
235
238
|
}
|
|
236
|
-
if (session.pushDisabled
|
|
239
|
+
if (session.pushDisabled) {
|
|
240
|
+
// Switched off (Settings toggle or config): take the device off the
|
|
241
|
+
// backend but keep the tokens, so switching back on re-registers
|
|
242
|
+
// without the host doing anything. `registered` empties at once,
|
|
243
|
+
// so later store updates do not repeat the release.
|
|
244
|
+
if (registered.size > 0) {
|
|
245
|
+
releasePushRegistration().catch(() => undefined);
|
|
246
|
+
}
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
if (!isReady(session)) {
|
|
237
250
|
return;
|
|
238
251
|
}
|
|
239
252
|
runTokenHook(session);
|
package/src/theme/theme.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/** @format */
|
|
2
2
|
|
|
3
|
+
import { Appearance } from 'react-native';
|
|
4
|
+
|
|
3
5
|
/**
|
|
4
6
|
* Chat theme.
|
|
5
7
|
*
|
|
@@ -161,7 +163,10 @@ export const DARK_THEME: ChatThemeColors = {
|
|
|
161
163
|
/** The subset of IConfig the theme depends on (kept structural so the
|
|
162
164
|
* helpers can be called with partial configs in tests). */
|
|
163
165
|
export interface ThemeConfigInput {
|
|
164
|
-
dark
|
|
166
|
+
/** `true` forces dark, `'system'` follows the OS appearance (pass the
|
|
167
|
+
* current scheme as `systemDark` to resolveTheme / isDarkTheme; omitted,
|
|
168
|
+
* the OS scheme is read directly). */
|
|
169
|
+
dark?: boolean | 'system';
|
|
165
170
|
darkColors?: ChatThemeOverrides;
|
|
166
171
|
colors?: {
|
|
167
172
|
primary?: string;
|
|
@@ -179,8 +184,16 @@ export interface ThemeConfigInput {
|
|
|
179
184
|
backgroundChat?: { color?: string };
|
|
180
185
|
}
|
|
181
186
|
|
|
182
|
-
|
|
183
|
-
|
|
187
|
+
/** The OS appearance right now — the fallback when a caller has no hook. */
|
|
188
|
+
// Optional chaining on `Appearance` itself: tests that mock react-native
|
|
189
|
+
// partially leave it undefined, and a missing module must read as light.
|
|
190
|
+
const systemIsDark = (): boolean => Appearance?.getColorScheme?.() === 'dark';
|
|
191
|
+
|
|
192
|
+
export const isDarkTheme = (
|
|
193
|
+
config?: ThemeConfigInput | null,
|
|
194
|
+
systemDark: boolean = systemIsDark()
|
|
195
|
+
): boolean =>
|
|
196
|
+
config?.dark === 'system' ? systemDark : config?.dark === true;
|
|
184
197
|
|
|
185
198
|
const pick = <T>(...values: (T | undefined | null | '')[]): T | undefined =>
|
|
186
199
|
values.find((v) => v !== undefined && v !== null && v !== '') as
|
|
@@ -196,8 +209,11 @@ const stripUndefined = (o: ChatThemeOverrides): ChatThemeOverrides =>
|
|
|
196
209
|
* Build the effective palette for a config. Pure; memoize at the call
|
|
197
210
|
* site (useTheme does).
|
|
198
211
|
*/
|
|
199
|
-
export const resolveTheme = (
|
|
200
|
-
|
|
212
|
+
export const resolveTheme = (
|
|
213
|
+
config?: ThemeConfigInput | null,
|
|
214
|
+
systemDark?: boolean
|
|
215
|
+
): ChatTheme => {
|
|
216
|
+
if (isDarkTheme(config, systemDark)) {
|
|
201
217
|
const overrides = stripUndefined(config?.darkColors ?? {});
|
|
202
218
|
const primary = pick(overrides.primary, DARK_THEME.primary)!;
|
|
203
219
|
return {
|
|
@@ -241,3 +257,21 @@ export const resolveTheme = (config?: ThemeConfigInput | null): ChatTheme => {
|
|
|
241
257
|
statusBarStyle: 'dark-content',
|
|
242
258
|
};
|
|
243
259
|
};
|
|
260
|
+
|
|
261
|
+
/** In-app appearance choice from Settings; `undefined` = follow the host's config.dark. */
|
|
262
|
+
export type ThemePreference = 'light' | 'dark' | 'system';
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Fold the user's in-app appearance choice into a config: the choice wins
|
|
266
|
+
* over the host's `dark` (a host that wants to lock the theme hides the
|
|
267
|
+
* setting with `settings.hideAppearance`). Returns the same object when
|
|
268
|
+
* nothing changes, so memoised consumers do not re-render.
|
|
269
|
+
*/
|
|
270
|
+
export const applyThemePreference = <T extends { dark?: boolean | 'system' }>(
|
|
271
|
+
config: T | undefined,
|
|
272
|
+
preference?: ThemePreference
|
|
273
|
+
): T | undefined => {
|
|
274
|
+
if (!preference || !config) {return config;}
|
|
275
|
+
const dark = preference === 'system' ? ('system' as const) : preference === 'dark';
|
|
276
|
+
return config.dark === dark ? config : { ...config, dark };
|
|
277
|
+
};
|
package/src/types/types.ts
CHANGED
|
@@ -386,8 +386,10 @@ export interface IConfig {
|
|
|
386
386
|
* not applied — pass brand colours via `darkColors` instead.
|
|
387
387
|
*
|
|
388
388
|
* config: { dark: true, darkColors: { primary: '#7C3AED', surface: '#111' } }
|
|
389
|
+
*
|
|
390
|
+
* `'system'` follows the device appearance (light/dark) automatically.
|
|
389
391
|
*/
|
|
390
|
-
dark?: boolean;
|
|
392
|
+
dark?: boolean | 'system';
|
|
391
393
|
/** Per-entry overrides of the dark palette; see ChatThemeColors. */
|
|
392
394
|
darkColors?: ChatThemeOverrides;
|
|
393
395
|
/** Configurable font family / weights for the chat UI. See TypographyConfig. */
|
|
@@ -787,8 +789,29 @@ export interface IConfig {
|
|
|
787
789
|
firebaseConfig?: FBConfig;
|
|
788
790
|
};
|
|
789
791
|
|
|
792
|
+
/** Settings screen switches. */
|
|
793
|
+
settings?: {
|
|
794
|
+
/** Hide the Light / Dark / System appearance picker (host locks the theme via `dark`). */
|
|
795
|
+
hideAppearance?: boolean;
|
|
796
|
+
/** Hide the push-notifications toggle. */
|
|
797
|
+
hidePushToggle?: boolean;
|
|
798
|
+
};
|
|
799
|
+
|
|
790
800
|
// ----- event hooks -----
|
|
791
801
|
eventHandlers?: {
|
|
802
|
+
/**
|
|
803
|
+
* Fired when the user picks an appearance in Settings (and once on
|
|
804
|
+
* mount with the persisted choice). `isDark` is the resolved value
|
|
805
|
+
* for 'system'. Hosts use it to sync their own chrome (status bar).
|
|
806
|
+
*/
|
|
807
|
+
onThemeChange?: (preference: 'light' | 'dark' | 'system', isDark: boolean) => void;
|
|
808
|
+
/**
|
|
809
|
+
* Fired when the user toggles push notifications in Settings. The SDK
|
|
810
|
+
* itself stops delivering: off releases every device-token
|
|
811
|
+
* registration on the backend (tokens are kept), on registers them
|
|
812
|
+
* again. A host that also owns native push should mirror the choice.
|
|
813
|
+
*/
|
|
814
|
+
onPushNotificationsToggle?: (enabled: boolean) => void | Promise<void>;
|
|
792
815
|
onMessageSent?: (event: {
|
|
793
816
|
message: string;
|
|
794
817
|
roomJID: string;
|
package/src/version.ts
CHANGED