@planningcenter/chat-react-native 3.22.0 → 3.23.0-rc.1

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.
Files changed (54) hide show
  1. package/build/contexts/api_provider.d.ts.map +1 -1
  2. package/build/contexts/api_provider.js +9 -1
  3. package/build/contexts/api_provider.js.map +1 -1
  4. package/build/contexts/session_context.d.ts +8 -4
  5. package/build/contexts/session_context.d.ts.map +1 -1
  6. package/build/contexts/session_context.js +97 -36
  7. package/build/contexts/session_context.js.map +1 -1
  8. package/build/hooks/index.d.ts +1 -0
  9. package/build/hooks/index.d.ts.map +1 -1
  10. package/build/hooks/index.js +1 -0
  11. package/build/hooks/index.js.map +1 -1
  12. package/build/hooks/use_organization.js +1 -1
  13. package/build/hooks/use_organization.js.map +1 -1
  14. package/build/hooks/use_people_person.d.ts +18 -0
  15. package/build/hooks/use_people_person.d.ts.map +1 -0
  16. package/build/hooks/use_people_person.js +17 -0
  17. package/build/hooks/use_people_person.js.map +1 -0
  18. package/build/hooks/use_storage.js.map +1 -1
  19. package/build/screens/conversations/components/list_header_action_button.d.ts +20 -0
  20. package/build/screens/conversations/components/list_header_action_button.d.ts.map +1 -0
  21. package/build/screens/conversations/components/list_header_action_button.js +44 -0
  22. package/build/screens/conversations/components/list_header_action_button.js.map +1 -0
  23. package/build/screens/conversations/components/list_header_component.d.ts.map +1 -1
  24. package/build/screens/conversations/components/list_header_component.js +44 -14
  25. package/build/screens/conversations/components/list_header_component.js.map +1 -1
  26. package/build/screens/conversations/conversations_screen.d.ts.map +1 -1
  27. package/build/screens/conversations/conversations_screen.js +3 -49
  28. package/build/screens/conversations/conversations_screen.js.map +1 -1
  29. package/build/types/resources/organization.d.ts +1 -0
  30. package/build/types/resources/organization.d.ts.map +1 -1
  31. package/build/types/resources/organization.js.map +1 -1
  32. package/build/utils/session.d.ts +15 -1
  33. package/build/utils/session.d.ts.map +1 -1
  34. package/build/utils/session.js +20 -3
  35. package/build/utils/session.js.map +1 -1
  36. package/build/utils/session_manager.d.ts +21 -0
  37. package/build/utils/session_manager.d.ts.map +1 -0
  38. package/build/utils/session_manager.js +58 -0
  39. package/build/utils/session_manager.js.map +1 -0
  40. package/package.json +2 -2
  41. package/src/__tests__/contexts/session_context.tsx +80 -76
  42. package/src/contexts/api_provider.tsx +10 -1
  43. package/src/contexts/session_context.tsx +129 -54
  44. package/src/hooks/index.ts +1 -0
  45. package/src/hooks/use_organization.ts +1 -1
  46. package/src/hooks/use_people_person.ts +33 -0
  47. package/src/hooks/use_storage.ts +2 -2
  48. package/src/screens/conversations/components/list_header_action_button.tsx +76 -0
  49. package/src/screens/conversations/components/list_header_component.tsx +67 -20
  50. package/src/screens/conversations/conversations_screen.tsx +4 -68
  51. package/src/types/resources/organization.ts +1 -0
  52. package/src/utils/__tests__/session_manager.test.ts +320 -0
  53. package/src/utils/session.ts +38 -5
  54. package/src/utils/session_manager.ts +74 -0
@@ -1 +1 @@
1
- {"version":3,"file":"api_provider.d.ts","sourceRoot":"","sources":["../../src/contexts/api_provider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,WAAW,EAIZ,MAAM,uBAAuB,CAAA;AAC9B,OAAO,KAAwC,MAAM,OAAO,CAAA;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAkBxC,eAAO,MAAM,eAAe,aAO1B,CAAA;AAEF,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,EAAE,SAAS,qBAsBlD;AAcD,wBAAgB,eAAe,WAQ9B"}
1
+ {"version":3,"file":"api_provider.d.ts","sourceRoot":"","sources":["../../src/contexts/api_provider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,WAAW,EAIZ,MAAM,uBAAuB,CAAA;AAC9B,OAAO,KAAwC,MAAM,OAAO,CAAA;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAmBxC,eAAO,MAAM,eAAe,aAO1B,CAAA;AAEF,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,EAAE,SAAS,qBA2BlD;AAcD,wBAAgB,eAAe,WAQ9B"}
@@ -1,7 +1,8 @@
1
1
  import { focusManager, QueryClient, QueryClientProvider, usePrefetchQuery, } from '@tanstack/react-query';
2
2
  import React, { useContext, useEffect, useRef } from 'react';
3
3
  import { ChatContext } from './chat_context';
4
- import { appGrantsRequestArgs, getRequestQueryKey } from '../hooks';
4
+ import { getRequestQueryKey } from '../hooks/use_suspense_api';
5
+ import { appGrantsRequestArgs } from '../hooks/use_chat_permissions';
5
6
  import { useApiClient } from '../hooks/use_api_client';
6
7
  import { useAppState } from '../hooks/use_app_state';
7
8
  let apiClient;
@@ -27,6 +28,10 @@ export function ApiProvider({ children }) {
27
28
  useEffect(() => {
28
29
  if (!sessionChanged)
29
30
  return;
31
+ if (chatQueryClient.isFetching()) {
32
+ chatQueryClient.invalidateQueries();
33
+ return;
34
+ }
30
35
  chatQueryClient.clear();
31
36
  }, [sessionChanged]);
32
37
  useEffect(() => {
@@ -57,6 +62,9 @@ export function useFocusManager() {
57
62
  function useSessionChanged(value) {
58
63
  const { token: newToken, env: newEnv } = value;
59
64
  const { token: prevToken, env: prevEnv } = usePrevious(value);
65
+ const isInitialLogin = !prevToken && !!newToken;
66
+ if (isInitialLogin)
67
+ return false;
60
68
  return Boolean(prevToken && newToken !== prevToken) || Boolean(prevEnv && newEnv !== prevEnv);
61
69
  }
62
70
  function usePrevious(value) {
@@ -1 +1 @@
1
- {"version":3,"file":"api_provider.js","sourceRoot":"","sources":["../../src/contexts/api_provider.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,WAAW,EACX,mBAAmB,EAEnB,gBAAgB,GACjB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,KAAK,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAE5D,OAAO,EAAE,WAAW,EAAoB,MAAM,gBAAgB,CAAA;AAC9D,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAmB,MAAM,UAAU,CAAA;AACpF,OAAO,EAAa,YAAY,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAEpD,IAAI,SAAgC,CAAA;AAEpC,MAAM,cAAc,GAAG,CAAC,EAAE,QAAQ,EAA0B,EAAE,EAAE;IAC9D,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAA;IACrC,CAAC;IAED,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,GAAG,MAAM,CAAC,GAAG,QAA2B,CAAA;IAEtE,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAA;AACnD,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,WAAW,CAAC;IAC7C,cAAc,EAAE;QACd,OAAO,EAAE;YACP,OAAO,EAAE,cAAc;YACvB,KAAK,EAAE,CAAC;SACT;KACF;CACF,CAAC,CAAA;AAEF,MAAM,UAAU,WAAW,CAAC,EAAE,QAAQ,EAAa;IACjD,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,CAAA;IAC9C,MAAM,cAAc,GAAG,iBAAiB,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAA;IAExD,MAAM,MAAM,GAAG,YAAY,EAAE,CAAA;IAE7B,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,cAAc;YAAE,OAAM;QAE3B,eAAe,CAAC,KAAK,EAAE,CAAA;IACzB,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,CAAA;IAEpB,SAAS,CAAC,GAAG,EAAE;QACb,SAAS,GAAG,MAAM,CAAA;IACpB,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA;IAEZ,OAAO,CACL,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAC3C;MAAA,CAAC,eAAe,CAAC,AAAD,EAChB;MAAA,CAAC,QAAQ,CACX;IAAA,EAAE,mBAAmB,CAAC,CACvB,CAAA;AACH,CAAC;AAED,wDAAwD;AACxD,0EAA0E;AAC1E,4BAA4B;AAC5B,MAAM,eAAe,GAAG,GAAG,EAAE;IAC3B,gBAAgB,CAAC;QACf,QAAQ,EAAE,kBAAkB,CAAC,oBAAoB,CAAC;QAClD,OAAO,EAAE,cAAc;KACxB,CAAC,CAAA;IAEF,OAAO,IAAI,CAAA;AACb,CAAC,CAAA;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAA;IAE9B,SAAS,CAAC,GAAG,EAAE;QACb,YAAY,CAAC,UAAU,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAA;IAChD,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;IAEd,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,SAAS,iBAAiB,CAAC,KAA8C;IACvE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,KAAK,CAAA;IAC9C,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,WAAW,CAAe,KAAK,CAAC,CAAA;IAE3E,OAAO,OAAO,CAAC,SAAS,IAAI,QAAQ,KAAK,SAAS,CAAC,IAAI,OAAO,CAAC,OAAO,IAAI,MAAM,KAAK,OAAO,CAAC,CAAA;AAC/F,CAAC;AAED,SAAS,WAAW,CAAI,KAAQ;IAC9B,MAAM,GAAG,GAAG,MAAM,CAAI,KAAK,CAAC,CAAA;IAE5B,SAAS,CAAC,GAAG,EAAE;QACb,GAAG,CAAC,OAAO,GAAG,KAAK,CAAA;IACrB,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAA;IAEX,OAAO,GAAG,CAAC,OAAO,CAAA;AACpB,CAAC","sourcesContent":["import {\n focusManager,\n QueryClient,\n QueryClientProvider,\n QueryKey,\n usePrefetchQuery,\n} from '@tanstack/react-query'\nimport React, { useContext, useEffect, useRef } from 'react'\nimport { ViewProps } from 'react-native'\nimport { ChatContext, ChatContextValue } from './chat_context'\nimport { appGrantsRequestArgs, getRequestQueryKey, RequestQueryKey } from '../hooks'\nimport { ApiClient, useApiClient } from '../hooks/use_api_client'\nimport { useAppState } from '../hooks/use_app_state'\n\nlet apiClient: ApiClient | undefined\n\nconst defaultQueryFn = ({ queryKey }: { queryKey: QueryKey }) => {\n if (!apiClient) {\n throw new Error('No token present')\n }\n\n const [url, data, headers, app = 'chat'] = queryKey as RequestQueryKey\n\n return apiClient[app].get({ url, data, headers })\n}\n\nexport const chatQueryClient = new QueryClient({\n defaultOptions: {\n queries: {\n queryFn: defaultQueryFn,\n retry: 3,\n },\n },\n})\n\nexport function ApiProvider({ children }: ViewProps) {\n const { token, env } = useContext(ChatContext)\n const sessionChanged = useSessionChanged({ token, env })\n\n const client = useApiClient()\n\n useEffect(() => {\n if (!sessionChanged) return\n\n chatQueryClient.clear()\n }, [sessionChanged])\n\n useEffect(() => {\n apiClient = client\n }, [client])\n\n return (\n <QueryClientProvider client={chatQueryClient}>\n <PrefetchQueries />\n {children}\n </QueryClientProvider>\n )\n}\n\n// Component to prefetch queries when the app is focused\n// This needs to live in the provider so that it can access the api client\n// and the chat query client\nconst PrefetchQueries = () => {\n usePrefetchQuery({\n queryKey: getRequestQueryKey(appGrantsRequestArgs),\n queryFn: defaultQueryFn,\n })\n\n return null\n}\n\nexport function useFocusManager() {\n const appState = useAppState()\n\n useEffect(() => {\n focusManager.setFocused(appState === 'active')\n }, [appState])\n\n return appState\n}\n\nfunction useSessionChanged(value: Pick<ChatContextValue, 'token' | 'env'>): boolean {\n const { token: newToken, env: newEnv } = value\n const { token: prevToken, env: prevEnv } = usePrevious<typeof value>(value)\n\n return Boolean(prevToken && newToken !== prevToken) || Boolean(prevEnv && newEnv !== prevEnv)\n}\n\nfunction usePrevious<T>(value: T): T {\n const ref = useRef<T>(value)\n\n useEffect(() => {\n ref.current = value\n }, [value])\n\n return ref.current\n}\n"]}
1
+ {"version":3,"file":"api_provider.js","sourceRoot":"","sources":["../../src/contexts/api_provider.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n focusManager,\n QueryClient,\n QueryClientProvider,\n QueryKey,\n usePrefetchQuery,\n} from '@tanstack/react-query'\nimport React, { useContext, useEffect, useRef } from 'react'\nimport { ViewProps } from 'react-native'\nimport { ChatContext, ChatContextValue } from './chat_context'\nimport { getRequestQueryKey, RequestQueryKey } from '../hooks/use_suspense_api'\nimport { appGrantsRequestArgs } from '../hooks/use_chat_permissions'\nimport { ApiClient, useApiClient } from '../hooks/use_api_client'\nimport { useAppState } from '../hooks/use_app_state'\n\nlet apiClient: ApiClient | undefined\n\nconst defaultQueryFn = ({ queryKey }: { queryKey: QueryKey }) => {\n if (!apiClient) {\n throw new Error('No token present')\n }\n\n const [url, data, headers, app = 'chat'] = queryKey as RequestQueryKey\n\n return apiClient[app].get({ url, data, headers })\n}\n\nexport const chatQueryClient = new QueryClient({\n defaultOptions: {\n queries: {\n queryFn: defaultQueryFn,\n retry: 3,\n },\n },\n})\n\nexport function ApiProvider({ children }: ViewProps) {\n const { token, env } = useContext(ChatContext)\n const sessionChanged = useSessionChanged({ token, env })\n\n const client = useApiClient()\n\n useEffect(() => {\n if (!sessionChanged) return\n\n if (chatQueryClient.isFetching()) {\n chatQueryClient.invalidateQueries()\n return\n }\n\n chatQueryClient.clear()\n }, [sessionChanged])\n\n useEffect(() => {\n apiClient = client\n }, [client])\n\n return (\n <QueryClientProvider client={chatQueryClient}>\n <PrefetchQueries />\n {children}\n </QueryClientProvider>\n )\n}\n\n// Component to prefetch queries when the app is focused\n// This needs to live in the provider so that it can access the api client\n// and the chat query client\nconst PrefetchQueries = () => {\n usePrefetchQuery({\n queryKey: getRequestQueryKey(appGrantsRequestArgs),\n queryFn: defaultQueryFn,\n })\n\n return null\n}\n\nexport function useFocusManager() {\n const appState = useAppState()\n\n useEffect(() => {\n focusManager.setFocused(appState === 'active')\n }, [appState])\n\n return appState\n}\n\nfunction useSessionChanged(value: Pick<ChatContextValue, 'token' | 'env'>): boolean {\n const { token: newToken, env: newEnv } = value\n const { token: prevToken, env: prevEnv } = usePrevious<typeof value>(value)\n\n const isInitialLogin = !prevToken && !!newToken\n if (isInitialLogin) return false\n\n return Boolean(prevToken && newToken !== prevToken) || Boolean(prevEnv && newEnv !== prevEnv)\n}\n\nfunction usePrevious<T>(value: T): T {\n const ref = useRef<T>(value)\n\n useEffect(() => {\n ref.current = value\n }, [value])\n\n return ref.current\n}\n"]}
@@ -1,20 +1,23 @@
1
- import { Session, ENV } from '../utils';
2
- import { FailedResponse, OAuthToken } from '../types';
3
1
  import { QueryClient } from '@tanstack/react-query';
4
2
  import React, { PropsWithChildren } from 'react';
3
+ import { FailedResponse, OAuthToken } from '../types';
4
+ import { ENV, Session } from '../utils';
5
5
  import { StorageAdapter } from '../utils/native_adapters/storage_adapter';
6
+ type Sessions = Record<string, string>;
6
7
  export type SessionContextValue = {
7
8
  env: ENV;
8
9
  setEnv: (_env: ENV) => void;
9
10
  session: Session;
11
+ sessions: Sessions;
10
12
  token: OAuthToken | undefined;
11
13
  handleUnauthorizedResponse: (_response: FailedResponse) => void;
12
14
  logout: () => void;
13
15
  setToken: (_token: OAuthToken) => void;
16
+ switchSession: (_sessionId: string) => void;
17
+ createSession: (_session: Session) => Promise<void>;
14
18
  };
15
19
  export declare const SessionContext: React.Context<SessionContextValue>;
16
20
  export type SessionContextConfig = {
17
- storage: StorageAdapter;
18
21
  secureStorage: StorageAdapter;
19
22
  refreshTokenFn: (params: {
20
23
  refresh_token: string;
@@ -22,8 +25,8 @@ export type SessionContextConfig = {
22
25
  }) => Promise<OAuthToken>;
23
26
  onLogout: () => void | Promise<void>;
24
27
  storageKeys?: {
25
- env?: string;
26
28
  sessions?: string;
29
+ currentSessionId?: string;
27
30
  };
28
31
  alertConfig?: {
29
32
  title?: string;
@@ -37,4 +40,5 @@ export declare function SessionContextProvider({ children, queryClient, config,
37
40
  queryClient: QueryClient;
38
41
  config: SessionContextConfig;
39
42
  }>): React.JSX.Element;
43
+ export {};
40
44
  //# sourceMappingURL=session_context.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"session_context.d.ts","sourceRoot":"","sources":["../../src/contexts/session_context.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AACvC,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAErD,OAAO,EAAE,WAAW,EAAe,MAAM,uBAAuB,CAAA;AAChE,OAAO,KAAK,EAAE,EAEZ,iBAAiB,EAKlB,MAAM,OAAO,CAAA;AAGd,OAAO,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAA;AAEzE,MAAM,MAAM,mBAAmB,GAAG;IAChC,GAAG,EAAE,GAAG,CAAA;IACR,MAAM,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAA;IAC3B,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,UAAU,GAAG,SAAS,CAAA;IAC7B,0BAA0B,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,IAAI,CAAA;IAC/D,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,QAAQ,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAA;CACvC,CAAA;AAED,eAAO,MAAM,cAAc,oCAQzB,CAAA;AAaF,MAAM,MAAM,oBAAoB,GAAG;IAEjC,OAAO,EAAE,cAAc,CAAA;IACvB,aAAa,EAAE,cAAc,CAAA;IAG7B,cAAc,EAAE,CAAC,MAAM,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,GAAG,CAAA;KAAE,KAAK,OAAO,CAAC,UAAU,CAAC,CAAA;IACpF,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAGpC,WAAW,CAAC,EAAE;QACZ,GAAG,CAAC,EAAE,MAAM,CAAA;QACZ,QAAQ,CAAC,EAAE,MAAM,CAAA;KAClB,CAAA;IACD,WAAW,CAAC,EAAE;QACZ,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,UAAU,CAAC,EAAE,MAAM,CAAA;KACpB,CAAA;IACD,UAAU,CAAC,EAAE,GAAG,CAAA;CACjB,CAAA;AAED,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,WAAW,EACX,MAAM,GACP,EAAE,iBAAiB,CAAC;IAAE,WAAW,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,oBAAoB,CAAA;CAAE,CAAC,qBA+J/E"}
1
+ {"version":3,"file":"session_context.d.ts","sourceRoot":"","sources":["../../src/contexts/session_context.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAe,MAAM,uBAAuB,CAAA;AAChE,OAAO,KAAK,EAAE,EAEZ,iBAAiB,EAKlB,MAAM,OAAO,CAAA;AAKd,OAAO,EAAyB,cAAc,EAAE,UAAU,EAAwB,MAAM,UAAU,CAAA;AAElG,OAAO,EAAE,GAAG,EAAgB,OAAO,EAA8B,MAAM,UAAU,CAAA;AAEjF,OAAO,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAA;AAIzE,KAAK,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAEtC,MAAM,MAAM,mBAAmB,GAAG;IAChC,GAAG,EAAE,GAAG,CAAA;IACR,MAAM,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAA;IAC3B,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,EAAE,QAAQ,CAAA;IAClB,KAAK,EAAE,UAAU,GAAG,SAAS,CAAA;IAC7B,0BAA0B,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,IAAI,CAAA;IAC/D,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,QAAQ,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAA;IACtC,aAAa,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAA;IAC3C,aAAa,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACpD,CAAA;AAED,eAAO,MAAM,cAAc,oCAWzB,CAAA;AAEF,MAAM,MAAM,oBAAoB,GAAG;IAEjC,aAAa,EAAE,cAAc,CAAA;IAG7B,cAAc,EAAE,CAAC,MAAM,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,GAAG,CAAA;KAAE,KAAK,OAAO,CAAC,UAAU,CAAC,CAAA;IACpF,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAGpC,WAAW,CAAC,EAAE;QACZ,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,gBAAgB,CAAC,EAAE,MAAM,CAAA;KAC1B,CAAA;IACD,WAAW,CAAC,EAAE;QACZ,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,UAAU,CAAC,EAAE,MAAM,CAAA;KACpB,CAAA;IACD,UAAU,CAAC,EAAE,GAAG,CAAA;CACjB,CAAA;AAgCD,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,WAAW,EACX,MAAM,GACP,EAAE,iBAAiB,CAAC;IAAE,WAAW,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,oBAAoB,CAAA;CAAE,CAAC,qBA2M/E"}
@@ -1,40 +1,63 @@
1
- import { Session } from '../utils';
2
- import { chatQueryClient } from './api_provider';
3
1
  import { useMutation } from '@tanstack/react-query';
4
2
  import React, { createContext, useCallback, useEffect, useMemo, useState, } from 'react';
5
3
  import { Alert } from 'react-native';
4
+ import { currentPersonQueryKey } from '../hooks/use_current_person';
5
+ import { organizationRequestArgs } from '../hooks/use_organization';
6
+ import { getRequestQueryKey } from '../hooks/use_suspense_api';
7
+ import { Session, UNAUTHENTICATED_SESSION_ID } from '../utils';
8
+ import { SessionManager } from '../utils/session_manager';
9
+ import { chatQueryClient } from './api_provider';
6
10
  import { useStorage } from '../hooks/use_storage';
7
11
  export const SessionContext = createContext({
8
12
  env: 'production',
9
13
  setEnv: () => null,
10
14
  session: new Session(),
15
+ sessions: {},
11
16
  token: undefined,
12
17
  handleUnauthorizedResponse: () => null,
13
18
  logout: () => null,
14
19
  setToken: () => null,
20
+ switchSession: () => null,
21
+ createSession: () => Promise.resolve(),
15
22
  });
16
- const environments = ['production', 'staging', 'development'];
17
- const initialSessions = environments.reduce((acc, env) => {
18
- const sessionProps = { env, token: undefined };
19
- acc[env] = new Session(sessionProps).toString();
20
- return acc;
21
- }, {});
23
+ const decorateSession = async (session) => {
24
+ if (!session.isAuthenticated)
25
+ return session;
26
+ const { data: personData } = await chatQueryClient.fetchQuery({
27
+ queryKey: currentPersonQueryKey,
28
+ });
29
+ const { data: organizationData } = await chatQueryClient.fetchQuery({
30
+ queryKey: getRequestQueryKey(organizationRequestArgs),
31
+ });
32
+ if (personData) {
33
+ const { name, avatar, id } = personData || {};
34
+ session.setPerson({ id, type: 'Person', name, avatar });
35
+ }
36
+ if (organizationData) {
37
+ session.setOrganization({
38
+ id: organizationData.id,
39
+ type: 'Organization',
40
+ name: organizationData.name,
41
+ });
42
+ }
43
+ return session;
44
+ };
22
45
  export function SessionContextProvider({ children, queryClient, config, }) {
23
- const { storage, secureStorage, refreshTokenFn, onLogout, storageKeys = {}, alertConfig = {}, defaultEnv = 'production', } = config;
24
- const envKey = storageKeys.env || 'env';
46
+ const { secureStorage, refreshTokenFn, onLogout, storageKeys = {}, alertConfig = {} } = config;
25
47
  const sessionsKey = storageKeys.sessions || 'sessions-storage';
26
- const [env, setEnv] = useStorage(storage, envKey, defaultEnv);
27
- const [sessions, setSessions] = useStorage(secureStorage, sessionsKey, initialSessions);
48
+ const [managerString, setManagerString] = useStorage(secureStorage, sessionsKey, '');
49
+ const sessionManager = useMemo(() => SessionManager.hydrate(managerString), [managerString]);
50
+ const sessions = sessionManager.sessions;
51
+ const currentSession = sessionManager.currentSession;
28
52
  const [alertShown, setAlertShown] = useState(false);
29
- const session = useMemo(() => Session.hydrate(sessions[env]), [sessions, env]);
30
- const { token } = session;
53
+ const { token } = currentSession;
31
54
  const { mutate: refreshToken, isPending: isRefreshingToken, isError: isRefreshError, } = useMutation({
32
55
  mutationKey: ['refresh-token', token?.refresh_token],
33
56
  mutationFn: () => {
34
57
  if (!token?.refresh_token) {
35
58
  return Promise.reject(new Error('Refresh token is required'));
36
59
  }
37
- return refreshTokenFn({ refresh_token: token.refresh_token, env: session.env }).then(handleTokenUpdate);
60
+ return refreshTokenFn({ refresh_token: token.refresh_token, env: currentSession.env }).then(handleTokenUpdate);
38
61
  },
39
62
  onError: (t) => {
40
63
  handleRefreshFailed(t);
@@ -44,26 +67,52 @@ export function SessionContextProvider({ children, queryClient, config, }) {
44
67
  chatQueryClient.clear();
45
68
  queryClient.clear();
46
69
  }, [queryClient]);
47
- const handleSetEnv = useCallback((_env) => {
48
- setEnv(_env);
49
- handleClearQueryClient();
50
- }, [handleClearQueryClient, setEnv]);
70
+ const handleSetEnv = useCallback(async (_env) => {
71
+ const updatedManager = SessionManager.hydrate(managerString);
72
+ const session = updatedManager.currentSession;
73
+ if (_env === session.env)
74
+ return;
75
+ const productionEnvironments = ['production', 'staging'];
76
+ const switchingToDevelopment = _env === 'development' && productionEnvironments.includes(session.env);
77
+ const switchingToProduction = _env === 'production' && session.env === 'development';
78
+ if (switchingToDevelopment || switchingToProduction) {
79
+ const newSession = new Session({ env: _env });
80
+ updatedManager.upsertSession(newSession);
81
+ }
82
+ updatedManager.setEnv(_env);
83
+ await setManagerString(updatedManager.toString());
84
+ }, [managerString, setManagerString]);
85
+ const handleCreateSession = useCallback(async (session) => {
86
+ const updatedManager = SessionManager.hydrate(managerString);
87
+ updatedManager.sessions[session.id] = session.toString();
88
+ updatedManager.currentSessionId = session.id;
89
+ await setManagerString(updatedManager.toString());
90
+ }, [managerString, setManagerString]);
91
+ const handleSwitchSession = useCallback(async (sessionId) => {
92
+ const updatedManager = SessionManager.hydrate(managerString);
93
+ try {
94
+ updatedManager.switchSession(sessionId);
95
+ }
96
+ catch (error) {
97
+ Alert.alert('Error', 'Session is not authenticated');
98
+ }
99
+ await setManagerString(updatedManager.toString());
100
+ }, [managerString, setManagerString]);
51
101
  const handleLogout = useCallback(async () => {
52
102
  handleClearQueryClient();
53
- return setSessions({
54
- ...sessions,
55
- [env]: new Session({ env }).toString(),
56
- }).then(() => onLogout());
57
- }, [env, sessions, setSessions, handleClearQueryClient, onLogout]);
58
- const handleTokenUpdate = useCallback((t) => {
59
- if (!t || !session)
60
- return t;
61
- session.token = t;
62
- return setSessions({
63
- ...sessions,
64
- [env]: session?.toString(),
65
- }).then(() => t);
66
- }, [env, session, sessions, setSessions]);
103
+ const manager = SessionManager.hydrate(managerString);
104
+ // Clear the current session ID
105
+ if (manager.currentSessionId) {
106
+ manager.removeSession(manager.currentSessionId);
107
+ await setManagerString(manager.toString());
108
+ }
109
+ return onLogout();
110
+ }, [managerString, setManagerString, handleClearQueryClient, onLogout]);
111
+ const handleTokenUpdate = useCallback(async (t) => {
112
+ const updatedManager = SessionManager.hydrate(managerString);
113
+ updatedManager.updateCurrentToken(t);
114
+ await setManagerString(updatedManager.toString());
115
+ }, [managerString, setManagerString]);
67
116
  const handleRefreshFailed = useCallback((t) => {
68
117
  if (t.status !== 401)
69
118
  return;
@@ -89,13 +138,16 @@ export function SessionContextProvider({ children, queryClient, config, }) {
89
138
  }
90
139
  }, [refreshToken, isRefreshingToken]);
91
140
  const sessionContextValue = {
92
- env: session.env,
93
- token: session.token,
94
- session,
141
+ env: currentSession.env,
142
+ token: currentSession.token,
143
+ session: currentSession,
144
+ sessions,
95
145
  logout: handleLogout,
96
146
  setToken: handleTokenUpdate,
97
147
  handleUnauthorizedResponse,
98
148
  setEnv: handleSetEnv,
149
+ switchSession: handleSwitchSession,
150
+ createSession: handleCreateSession,
99
151
  };
100
152
  const alertTitle = alertConfig.title || 'Oops';
101
153
  const alertMessage = alertConfig.message || 'Something went wrong with your login!';
@@ -126,6 +178,15 @@ export function SessionContextProvider({ children, queryClient, config, }) {
126
178
  retryText,
127
179
  logoutText,
128
180
  ]);
181
+ useEffect(() => {
182
+ const manager = SessionManager.hydrate(managerString);
183
+ if (manager.currentSessionId === UNAUTHENTICATED_SESSION_ID)
184
+ return;
185
+ decorateSession(manager.currentSession).then(async (decoratedSession) => {
186
+ manager.upsertSession(decoratedSession);
187
+ await setManagerString(manager.toString());
188
+ });
189
+ }, [managerString, setManagerString]);
129
190
  return <SessionContext.Provider value={sessionContextValue}>{children}</SessionContext.Provider>;
130
191
  }
131
192
  //# sourceMappingURL=session_context.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"session_context.js","sourceRoot":"","sources":["../../src/contexts/session_context.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Session, ENV } from '../utils'\nimport { FailedResponse, OAuthToken } from '../types'\nimport { chatQueryClient } from './api_provider'\nimport { QueryClient, useMutation } from '@tanstack/react-query'\nimport React, {\n createContext,\n PropsWithChildren,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react'\nimport { Alert } from 'react-native'\nimport { useStorage } from '../hooks/use_storage'\nimport { StorageAdapter } from '../utils/native_adapters/storage_adapter'\n\nexport type SessionContextValue = {\n env: ENV\n setEnv: (_env: ENV) => void\n session: Session\n token: OAuthToken | undefined\n handleUnauthorizedResponse: (_response: FailedResponse) => void\n logout: () => void\n setToken: (_token: OAuthToken) => void\n}\n\nexport const SessionContext = createContext<SessionContextValue>({\n env: 'production',\n setEnv: () => null,\n session: new Session(),\n token: undefined,\n handleUnauthorizedResponse: () => null,\n logout: () => null,\n setToken: () => null,\n})\n\ntype Sessions = Record<ENV, string>\nconst environments: ENV[] = ['production', 'staging', 'development']\n\nconst initialSessions = environments.reduce((acc, env) => {\n const sessionProps = { env, token: undefined }\n\n acc[env] = new Session(sessionProps).toString()\n\n return acc\n}, {} as Sessions)\n\nexport type SessionContextConfig = {\n // Storage adapters\n storage: StorageAdapter // For non-sensitive data (env preference)\n secureStorage: StorageAdapter // For sensitive data (tokens/sessions)\n\n // Functional callbacks\n refreshTokenFn: (params: { refresh_token: string; env: ENV }) => Promise<OAuthToken>\n onLogout: () => void | Promise<void>\n\n // Optional configuration\n storageKeys?: {\n env?: string\n sessions?: string\n }\n alertConfig?: {\n title?: string\n message?: string\n retryText?: string\n logoutText?: string\n }\n defaultEnv?: ENV\n}\n\nexport function SessionContextProvider({\n children,\n queryClient,\n config,\n}: PropsWithChildren<{ queryClient: QueryClient; config: SessionContextConfig }>) {\n const {\n storage,\n secureStorage,\n refreshTokenFn,\n onLogout,\n storageKeys = {},\n alertConfig = {},\n defaultEnv = 'production',\n } = config\n\n const envKey = storageKeys.env || 'env'\n const sessionsKey = storageKeys.sessions || 'sessions-storage'\n\n const [env, setEnv] = useStorage<ENV>(storage, envKey, defaultEnv)\n const [sessions, setSessions] = useStorage<Sessions>(secureStorage, sessionsKey, initialSessions)\n const [alertShown, setAlertShown] = useState(false)\n const session = useMemo(() => Session.hydrate<OAuthToken>(sessions[env]), [sessions, env])\n const { token } = session\n\n const {\n mutate: refreshToken,\n isPending: isRefreshingToken,\n isError: isRefreshError,\n } = useMutation({\n mutationKey: ['refresh-token', token?.refresh_token],\n mutationFn: () => {\n if (!token?.refresh_token) {\n return Promise.reject(new Error('Refresh token is required'))\n }\n return refreshTokenFn({ refresh_token: token.refresh_token, env: session.env }).then(\n handleTokenUpdate\n )\n },\n onError: (t: Partial<FailedResponse>) => {\n handleRefreshFailed(t)\n },\n })\n\n const handleClearQueryClient = useCallback(() => {\n chatQueryClient.clear()\n queryClient.clear()\n }, [queryClient])\n\n const handleSetEnv = useCallback(\n (_env: ENV) => {\n setEnv(_env)\n handleClearQueryClient()\n },\n [handleClearQueryClient, setEnv]\n )\n\n const handleLogout = useCallback(async () => {\n handleClearQueryClient()\n\n return setSessions({\n ...sessions,\n [env]: new Session({ env }).toString(),\n }).then(() => onLogout())\n }, [env, sessions, setSessions, handleClearQueryClient, onLogout])\n\n const handleTokenUpdate = useCallback(\n (t: OAuthToken) => {\n if (!t || !session) return t\n\n session.token = t\n\n return setSessions({\n ...sessions,\n [env]: session?.toString(),\n }).then(() => t)\n },\n [env, session, sessions, setSessions]\n )\n\n const handleRefreshFailed = useCallback(\n (t: Partial<FailedResponse>) => {\n if (t.status !== 401) return\n // If we didn't fail because of an unauthorized response ( 401 ),\n // it could be because we were unable to store the token.\n // Do not log out.\n\n const { errors = [] } = t\n // The code for a forced logout is \"capuchin\"\n const isForcedLogout = errors.some((e: { detail?: string }) =>\n /capuchin/i.test(e.detail || '')\n )\n\n if (isForcedLogout) {\n handleLogout()\n }\n },\n [handleLogout]\n )\n\n const handleUnauthorizedResponse = useCallback(\n async (response: FailedResponse) => {\n const { errors = [] } = response\n\n const isUnauthorized = errors.some((e: { detail?: string }) =>\n /TRASH_PANDA/i.test(e.detail || '')\n )\n\n if (isUnauthorized) return\n\n const isForcedLogout = errors.some((e: { detail?: string }) =>\n /capuchin/i.test(e.detail || '')\n )\n const isExpiredToken = errors.some((e: { detail?: string }) => /baboon/i.test(e.detail || ''))\n\n if (!isRefreshingToken || isExpiredToken || isForcedLogout) {\n refreshToken()\n }\n },\n [refreshToken, isRefreshingToken]\n )\n\n const sessionContextValue: SessionContextValue = {\n env: session.env,\n token: session.token,\n session,\n logout: handleLogout,\n setToken: handleTokenUpdate,\n handleUnauthorizedResponse,\n setEnv: handleSetEnv,\n }\n\n const alertTitle = alertConfig.title || 'Oops'\n const alertMessage = alertConfig.message || 'Something went wrong with your login!'\n const retryText = alertConfig.retryText || 'Keep trying'\n const logoutText = alertConfig.logoutText || 'Logout'\n\n useEffect(() => {\n if (isRefreshError && !alertShown && token?.refresh_token) {\n setAlertShown(true)\n Alert.alert(alertTitle, alertMessage, [\n {\n text: retryText,\n onPress: () => {\n refreshToken()\n setAlertShown(false)\n },\n },\n { text: logoutText, onPress: () => handleLogout() },\n ])\n }\n }, [\n isRefreshError,\n handleLogout,\n alertShown,\n refreshToken,\n token?.refresh_token,\n alertTitle,\n alertMessage,\n retryText,\n logoutText,\n ])\n\n return <SessionContext.Provider value={sessionContextValue}>{children}</SessionContext.Provider>\n}\n"]}
1
+ {"version":3,"file":"session_context.js","sourceRoot":"","sources":["../../src/contexts/session_context.tsx"],"names":[],"mappings":"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","sourcesContent":["import { QueryClient, useMutation } from '@tanstack/react-query'\nimport React, {\n createContext,\n PropsWithChildren,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react'\nimport { Alert } from 'react-native'\nimport { currentPersonQueryKey } from '../hooks/use_current_person'\nimport { organizationRequestArgs } from '../hooks/use_organization'\nimport { getRequestQueryKey } from '../hooks/use_suspense_api'\nimport { CurrentPersonResource, FailedResponse, OAuthToken, OrganizationResource } from '../types'\nimport { ApiResource } from '../types/api_primitives'\nimport { ENV, PartialToken, Session, UNAUTHENTICATED_SESSION_ID } from '../utils'\nimport { SessionManager } from '../utils/session_manager'\nimport { StorageAdapter } from '../utils/native_adapters/storage_adapter'\nimport { chatQueryClient } from './api_provider'\nimport { useStorage } from '../hooks/use_storage'\n\ntype Sessions = Record<string, string> // Key is session ID\n\nexport type SessionContextValue = {\n env: ENV\n setEnv: (_env: ENV) => void\n session: Session\n sessions: Sessions\n token: OAuthToken | undefined\n handleUnauthorizedResponse: (_response: FailedResponse) => void\n logout: () => void\n setToken: (_token: OAuthToken) => void\n switchSession: (_sessionId: string) => void\n createSession: (_session: Session) => Promise<void>\n}\n\nexport const SessionContext = createContext<SessionContextValue>({\n env: 'production',\n setEnv: () => null,\n session: new Session(),\n sessions: {},\n token: undefined,\n handleUnauthorizedResponse: () => null,\n logout: () => null,\n setToken: () => null,\n switchSession: () => null,\n createSession: () => Promise.resolve(),\n})\n\nexport type SessionContextConfig = {\n // Storage adapters\n secureStorage: StorageAdapter // For sensitive data (tokens/sessions)\n\n // Functional callbacks\n refreshTokenFn: (params: { refresh_token: string; env: ENV }) => Promise<OAuthToken>\n onLogout: () => void | Promise<void>\n\n // Optional configuration\n storageKeys?: {\n sessions?: string\n currentSessionId?: string\n }\n alertConfig?: {\n title?: string\n message?: string\n retryText?: string\n logoutText?: string\n }\n defaultEnv?: ENV\n}\n\nconst decorateSession = async <T extends PartialToken>(session: Session<T>) => {\n if (!session.isAuthenticated) return session\n\n const { data: personData } = await chatQueryClient.fetchQuery<ApiResource<CurrentPersonResource>>(\n {\n queryKey: currentPersonQueryKey,\n }\n )\n const { data: organizationData } = await chatQueryClient.fetchQuery<\n ApiResource<OrganizationResource>\n >({\n queryKey: getRequestQueryKey(organizationRequestArgs),\n })\n\n if (personData) {\n const { name, avatar, id } = personData || {}\n session.setPerson({ id, type: 'Person', name, avatar })\n }\n\n if (organizationData) {\n session.setOrganization({\n id: organizationData.id,\n type: 'Organization',\n name: organizationData.name,\n })\n }\n\n return session\n}\n\nexport function SessionContextProvider({\n children,\n queryClient,\n config,\n}: PropsWithChildren<{ queryClient: QueryClient; config: SessionContextConfig }>) {\n const { secureStorage, refreshTokenFn, onLogout, storageKeys = {}, alertConfig = {} } = config\n\n const sessionsKey = storageKeys.sessions || 'sessions-storage'\n const [managerString, setManagerString] = useStorage<string>(secureStorage, sessionsKey, '')\n const sessionManager = useMemo(() => SessionManager.hydrate(managerString), [managerString])\n\n const sessions = sessionManager.sessions\n const currentSession = sessionManager.currentSession\n\n const [alertShown, setAlertShown] = useState(false)\n\n const { token } = currentSession\n\n const {\n mutate: refreshToken,\n isPending: isRefreshingToken,\n isError: isRefreshError,\n } = useMutation({\n mutationKey: ['refresh-token', token?.refresh_token],\n mutationFn: () => {\n if (!token?.refresh_token) {\n return Promise.reject(new Error('Refresh token is required'))\n }\n return refreshTokenFn({ refresh_token: token.refresh_token, env: currentSession.env }).then(\n handleTokenUpdate\n )\n },\n onError: (t: Partial<FailedResponse>) => {\n handleRefreshFailed(t)\n },\n })\n\n const handleClearQueryClient = useCallback(() => {\n chatQueryClient.clear()\n queryClient.clear()\n }, [queryClient])\n\n const handleSetEnv = useCallback(\n async (_env: ENV) => {\n const updatedManager = SessionManager.hydrate(managerString)\n const session = updatedManager.currentSession\n if (_env === session.env) return\n\n const productionEnvironments = ['production', 'staging']\n const switchingToDevelopment =\n _env === 'development' && productionEnvironments.includes(session.env)\n const switchingToProduction = _env === 'production' && session.env === 'development'\n\n if (switchingToDevelopment || switchingToProduction) {\n const newSession = new Session({ env: _env })\n updatedManager.upsertSession(newSession)\n }\n\n updatedManager.setEnv(_env)\n await setManagerString(updatedManager.toString())\n },\n [managerString, setManagerString]\n )\n\n const handleCreateSession = useCallback(\n async (session: Session) => {\n const updatedManager = SessionManager.hydrate(managerString)\n updatedManager.sessions[session.id] = session.toString()\n updatedManager.currentSessionId = session.id\n await setManagerString(updatedManager.toString())\n },\n [managerString, setManagerString]\n )\n\n const handleSwitchSession = useCallback(\n async (sessionId: string) => {\n const updatedManager = SessionManager.hydrate(managerString)\n try {\n updatedManager.switchSession(sessionId)\n } catch (error) {\n Alert.alert('Error', 'Session is not authenticated')\n }\n await setManagerString(updatedManager.toString())\n },\n [managerString, setManagerString]\n )\n\n const handleLogout = useCallback(async () => {\n handleClearQueryClient()\n const manager = SessionManager.hydrate(managerString)\n\n // Clear the current session ID\n if (manager.currentSessionId) {\n manager.removeSession(manager.currentSessionId)\n await setManagerString(manager.toString())\n }\n\n return onLogout()\n }, [managerString, setManagerString, handleClearQueryClient, onLogout])\n\n const handleTokenUpdate = useCallback(\n async (t: OAuthToken) => {\n const updatedManager = SessionManager.hydrate(managerString)\n\n updatedManager.updateCurrentToken(t)\n await setManagerString(updatedManager.toString())\n },\n [managerString, setManagerString]\n )\n\n const handleRefreshFailed = useCallback(\n (t: Partial<FailedResponse>) => {\n if (t.status !== 401) return\n // If we didn't fail because of an unauthorized response ( 401 ),\n // it could be because we were unable to store the token.\n // Do not log out.\n\n const { errors = [] } = t\n // The code for a forced logout is \"capuchin\"\n const isForcedLogout = errors.some((e: { detail?: string }) =>\n /capuchin/i.test(e.detail || '')\n )\n\n if (isForcedLogout) {\n handleLogout()\n }\n },\n [handleLogout]\n )\n\n const handleUnauthorizedResponse = useCallback(\n async (response: FailedResponse) => {\n const { errors = [] } = response\n\n const isUnauthorized = errors.some((e: { detail?: string }) =>\n /TRASH_PANDA/i.test(e.detail || '')\n )\n\n if (isUnauthorized) return\n\n const isForcedLogout = errors.some((e: { detail?: string }) =>\n /capuchin/i.test(e.detail || '')\n )\n const isExpiredToken = errors.some((e: { detail?: string }) => /baboon/i.test(e.detail || ''))\n\n if (!isRefreshingToken || isExpiredToken || isForcedLogout) {\n refreshToken()\n }\n },\n [refreshToken, isRefreshingToken]\n )\n\n const sessionContextValue: SessionContextValue = {\n env: currentSession.env,\n token: currentSession.token as OAuthToken | undefined,\n session: currentSession,\n sessions,\n logout: handleLogout,\n setToken: handleTokenUpdate,\n handleUnauthorizedResponse,\n setEnv: handleSetEnv,\n switchSession: handleSwitchSession,\n createSession: handleCreateSession,\n }\n\n const alertTitle = alertConfig.title || 'Oops'\n const alertMessage = alertConfig.message || 'Something went wrong with your login!'\n const retryText = alertConfig.retryText || 'Keep trying'\n const logoutText = alertConfig.logoutText || 'Logout'\n\n useEffect(() => {\n if (isRefreshError && !alertShown && token?.refresh_token) {\n setAlertShown(true)\n Alert.alert(alertTitle, alertMessage, [\n {\n text: retryText,\n onPress: () => {\n refreshToken()\n setAlertShown(false)\n },\n },\n { text: logoutText, onPress: () => handleLogout() },\n ])\n }\n }, [\n isRefreshError,\n handleLogout,\n alertShown,\n refreshToken,\n token?.refresh_token,\n alertTitle,\n alertMessage,\n retryText,\n logoutText,\n ])\n\n useEffect(() => {\n const manager = SessionManager.hydrate(managerString)\n if (manager.currentSessionId === UNAUTHENTICATED_SESSION_ID) return\n\n decorateSession(manager.currentSession).then(async decoratedSession => {\n manager.upsertSession(decoratedSession)\n await setManagerString(manager.toString())\n })\n }, [managerString, setManagerString])\n\n return <SessionContext.Provider value={sessionContextValue}>{children}</SessionContext.Provider>\n}\n"]}
@@ -20,4 +20,5 @@ export * from './use_scalable_number_of_lines';
20
20
  export * from './use_submit_age_check';
21
21
  export * from './use_organization';
22
22
  export * from './use_product_analytics';
23
+ export * from './use_people_person';
23
24
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA;AACnC,cAAc,yCAAyC,CAAA;AACvD,cAAc,aAAa,CAAA;AAC3B,cAAc,oBAAoB,CAAA;AAClC,cAAc,sBAAsB,CAAA;AACpC,cAAc,oBAAoB,CAAA;AAClC,cAAc,kBAAkB,CAAA;AAChC,cAAc,mCAAmC,CAAA;AACjD,cAAc,wBAAwB,CAAA;AACtC,cAAc,kBAAkB,CAAA;AAChC,cAAc,qBAAqB,CAAA;AACnC,cAAc,cAAc,CAAA;AAC5B,cAAc,WAAW,CAAA;AACzB,cAAc,kBAAkB,CAAA;AAChC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,wBAAwB,CAAA;AACtC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,wBAAwB,CAAA;AACtC,cAAc,oBAAoB,CAAA;AAClC,cAAc,yBAAyB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA;AACnC,cAAc,yCAAyC,CAAA;AACvD,cAAc,aAAa,CAAA;AAC3B,cAAc,oBAAoB,CAAA;AAClC,cAAc,sBAAsB,CAAA;AACpC,cAAc,oBAAoB,CAAA;AAClC,cAAc,kBAAkB,CAAA;AAChC,cAAc,mCAAmC,CAAA;AACjD,cAAc,wBAAwB,CAAA;AACtC,cAAc,kBAAkB,CAAA;AAChC,cAAc,qBAAqB,CAAA;AACnC,cAAc,cAAc,CAAA;AAC5B,cAAc,WAAW,CAAA;AACzB,cAAc,kBAAkB,CAAA;AAChC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,wBAAwB,CAAA;AACtC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,wBAAwB,CAAA;AACtC,cAAc,oBAAoB,CAAA;AAClC,cAAc,yBAAyB,CAAA;AACvC,cAAc,qBAAqB,CAAA"}
@@ -20,4 +20,5 @@ export * from './use_scalable_number_of_lines';
20
20
  export * from './use_submit_age_check';
21
21
  export * from './use_organization';
22
22
  export * from './use_product_analytics';
23
+ export * from './use_people_person';
23
24
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA;AACnC,cAAc,yCAAyC,CAAA;AACvD,cAAc,aAAa,CAAA;AAC3B,cAAc,oBAAoB,CAAA;AAClC,cAAc,sBAAsB,CAAA;AACpC,cAAc,oBAAoB,CAAA;AAClC,cAAc,kBAAkB,CAAA;AAChC,cAAc,mCAAmC,CAAA;AACjD,cAAc,wBAAwB,CAAA;AACtC,cAAc,kBAAkB,CAAA;AAChC,cAAc,qBAAqB,CAAA;AACnC,cAAc,cAAc,CAAA;AAC5B,cAAc,WAAW,CAAA;AACzB,cAAc,kBAAkB,CAAA;AAChC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,wBAAwB,CAAA;AACtC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,wBAAwB,CAAA;AACtC,cAAc,oBAAoB,CAAA;AAClC,cAAc,yBAAyB,CAAA","sourcesContent":["export * from './use_async_storage'\nexport * from './use_animated_message_background_color'\nexport * from './use_theme'\nexport * from './use_suspense_api'\nexport * from './use_current_person'\nexport * from './use_deleting_ids'\nexport * from './use_font_scale'\nexport * from './use_create_android_ripple_color'\nexport * from './use_chat_permissions'\nexport * from './use_api_client'\nexport * from './use_groups_groups'\nexport * from './use_groups'\nexport * from './use_api'\nexport * from './use_api_client'\nexport * from './use_message_reaction_toggle'\nexport * from './use_interaction_ghost_color'\nexport * from './use_at_font_scale_breakpoint'\nexport * from './use_qualified_by_age'\nexport * from './use_scalable_number_of_lines'\nexport * from './use_submit_age_check'\nexport * from './use_organization'\nexport * from './use_product_analytics'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA;AACnC,cAAc,yCAAyC,CAAA;AACvD,cAAc,aAAa,CAAA;AAC3B,cAAc,oBAAoB,CAAA;AAClC,cAAc,sBAAsB,CAAA;AACpC,cAAc,oBAAoB,CAAA;AAClC,cAAc,kBAAkB,CAAA;AAChC,cAAc,mCAAmC,CAAA;AACjD,cAAc,wBAAwB,CAAA;AACtC,cAAc,kBAAkB,CAAA;AAChC,cAAc,qBAAqB,CAAA;AACnC,cAAc,cAAc,CAAA;AAC5B,cAAc,WAAW,CAAA;AACzB,cAAc,kBAAkB,CAAA;AAChC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,wBAAwB,CAAA;AACtC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,wBAAwB,CAAA;AACtC,cAAc,oBAAoB,CAAA;AAClC,cAAc,yBAAyB,CAAA;AACvC,cAAc,qBAAqB,CAAA","sourcesContent":["export * from './use_async_storage'\nexport * from './use_animated_message_background_color'\nexport * from './use_theme'\nexport * from './use_suspense_api'\nexport * from './use_current_person'\nexport * from './use_deleting_ids'\nexport * from './use_font_scale'\nexport * from './use_create_android_ripple_color'\nexport * from './use_chat_permissions'\nexport * from './use_api_client'\nexport * from './use_groups_groups'\nexport * from './use_groups'\nexport * from './use_api'\nexport * from './use_api_client'\nexport * from './use_message_reaction_toggle'\nexport * from './use_interaction_ghost_color'\nexport * from './use_at_font_scale_breakpoint'\nexport * from './use_qualified_by_age'\nexport * from './use_scalable_number_of_lines'\nexport * from './use_submit_age_check'\nexport * from './use_organization'\nexport * from './use_product_analytics'\nexport * from './use_people_person'\n"]}
@@ -3,7 +3,7 @@ export const organizationRequestArgs = {
3
3
  url: '/',
4
4
  data: {
5
5
  fields: {
6
- Organization: ['contact_email'],
6
+ Organization: ['contact_email', 'name', 'contact_phone_number'],
7
7
  },
8
8
  },
9
9
  app: 'chat',
@@ -1 +1 @@
1
- {"version":3,"file":"use_organization.js","sourceRoot":"","sources":["../../src/hooks/use_organization.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAGnD,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,GAAG,EAAE,GAAG;IACR,IAAI,EAAE;QACJ,MAAM,EAAE;YACN,YAAY,EAAE,CAAC,eAAe,CAAC;SAChC;KACF;IACD,GAAG,EAAE,MAAa;CACnB,CAAA;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,cAAc,CAAuB,uBAAuB,CAAC,CAAA;AACtE,CAAC","sourcesContent":["import { OrganizationResource } from '../types'\nimport { useSuspenseGet } from './use_suspense_api'\nimport { App } from './use_api_client'\n\nexport const organizationRequestArgs = {\n url: '/',\n data: {\n fields: {\n Organization: ['contact_email'],\n },\n },\n app: 'chat' as App,\n}\n\nexport function useOrganization() {\n return useSuspenseGet<OrganizationResource>(organizationRequestArgs)\n}\n"]}
1
+ {"version":3,"file":"use_organization.js","sourceRoot":"","sources":["../../src/hooks/use_organization.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAGnD,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,GAAG,EAAE,GAAG;IACR,IAAI,EAAE;QACJ,MAAM,EAAE;YACN,YAAY,EAAE,CAAC,eAAe,EAAE,MAAM,EAAE,sBAAsB,CAAC;SAChE;KACF;IACD,GAAG,EAAE,MAAa;CACnB,CAAA;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,cAAc,CAAuB,uBAAuB,CAAC,CAAA;AACtE,CAAC","sourcesContent":["import { OrganizationResource } from '../types'\nimport { useSuspenseGet } from './use_suspense_api'\nimport { App } from './use_api_client'\n\nexport const organizationRequestArgs = {\n url: '/',\n data: {\n fields: {\n Organization: ['contact_email', 'name', 'contact_phone_number'],\n },\n },\n app: 'chat' as App,\n}\n\nexport function useOrganization() {\n return useSuspenseGet<OrganizationResource>(organizationRequestArgs)\n}\n"]}
@@ -0,0 +1,18 @@
1
+ import { ResourceObject } from '../types/api_primitives';
2
+ type EmailResource = ResourceObject & {
3
+ type: 'Email';
4
+ primary: boolean;
5
+ address: string;
6
+ };
7
+ interface PeoplePerson extends ResourceObject {
8
+ type: 'Person';
9
+ id: number;
10
+ name: string;
11
+ avatar: string;
12
+ emails: EmailResource[];
13
+ }
14
+ export declare const usePeoplePerson: (person?: {
15
+ id: number;
16
+ }) => PeoplePerson | undefined;
17
+ export {};
18
+ //# sourceMappingURL=use_people_person.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use_people_person.d.ts","sourceRoot":"","sources":["../../src/hooks/use_people_person.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAGxD,KAAK,aAAa,GAAG,cAAc,GAAG;IACpC,IAAI,EAAE,OAAO,CAAA;IACb,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,UAAU,YAAa,SAAQ,cAAc;IAC3C,IAAI,EAAE,QAAQ,CAAA;IACd,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,aAAa,EAAE,CAAA;CACxB;AAED,eAAO,MAAM,eAAe,YAAa;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,6BAetD,CAAA"}
@@ -0,0 +1,17 @@
1
+ import { useApiGet } from './use_api';
2
+ export const usePeoplePerson = (person) => {
3
+ const { data: peoplePerson } = useApiGet({
4
+ url: `/people/${person?.id}`,
5
+ enabled: Boolean(person?.id),
6
+ data: {
7
+ include: ['emails'],
8
+ fields: {
9
+ Person: ['id', 'name', 'avatar', 'emails'],
10
+ Email: ['address', 'primary'],
11
+ },
12
+ },
13
+ app: 'people',
14
+ });
15
+ return peoplePerson;
16
+ };
17
+ //# sourceMappingURL=use_people_person.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use_people_person.js","sourceRoot":"","sources":["../../src/hooks/use_people_person.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAgBrC,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,MAAuB,EAAE,EAAE;IACzD,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,SAAS,CAAe;QACrD,GAAG,EAAE,WAAW,MAAM,EAAE,EAAE,EAAE;QAC5B,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QAC5B,IAAI,EAAE;YACJ,OAAO,EAAE,CAAC,QAAQ,CAAC;YACnB,MAAM,EAAE;gBACN,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC;gBAC1C,KAAK,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;aAC9B;SACF;QACD,GAAG,EAAE,QAAQ;KACd,CAAC,CAAA;IAEF,OAAO,YAAY,CAAA;AACrB,CAAC,CAAA","sourcesContent":["import { ResourceObject } from '../types/api_primitives'\nimport { useApiGet } from './use_api'\n\ntype EmailResource = ResourceObject & {\n type: 'Email'\n primary: boolean\n address: string\n}\n\ninterface PeoplePerson extends ResourceObject {\n type: 'Person'\n id: number\n name: string\n avatar: string\n emails: EmailResource[]\n}\n\nexport const usePeoplePerson = (person?: { id: number }) => {\n const { data: peoplePerson } = useApiGet<PeoplePerson>({\n url: `/people/${person?.id}`,\n enabled: Boolean(person?.id),\n data: {\n include: ['emails'],\n fields: {\n Person: ['id', 'name', 'avatar', 'emails'],\n Email: ['address', 'primary'],\n },\n },\n app: 'people',\n })\n\n return peoplePerson\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"use_storage.js","sourceRoot":"","sources":["../../src/hooks/use_storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AAGnC,MAAM,iBAAiB,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,CAAC,mBAAmB,GAAG,EAAE,CAAC,CAAA;AAIrE;;;GAGG;AACH,MAAM,UAAU,UAAU,CACxB,OAAuB,EACvB,GAAW,EACX,YAAwB,EACxB,eAAwB,KAAK;IAE7B,MAAM,QAAQ,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAA;IAEvC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,gBAAgB,CAAa;QAC5D,QAAQ,EAAE,QAAQ;QAClB,OAAO,EAAE,GAAG,EAAE,CACZ,OAAO;aACJ,OAAO,CAAC,GAAG,CAAC;aACZ,IAAI,CAAC,WAAW,CAAC,EAAE;YAClB,IAAI,CAAC,WAAW;gBAAE,OAAO,YAAY,CAAA;YAErC,IAAI,CAAC;gBACH,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAA;YAChC,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,WAAW,CAAA;YACpB,CAAC;QACH,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,CAAC,EAAE;YACT,IAAI,CAAC,YAAY;gBAAE,OAAO,YAAY,CAAA;YAEtC,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QAC1B,CAAC,CAAC;KACP,CAAC,CAAA;IAEF,MAAM,QAAQ,GAAyB,WAAW,CAChD,SAAS,CAAC,EAAE;QACV,IAAI,SAAS,KAAK,IAAI,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAClD,OAAO,OAAO;iBACX,UAAU,CAAC,GAAG,CAAC;iBACf,IAAI,CAAC,GAAG,EAAE;gBACT,OAAO,EAAE,CAAA;YACX,CAAC,CAAC;iBACD,KAAK,CAAC,IAAI,CAAC,CAAA;QAChB,CAAC;QAED,OAAO,OAAO;aACX,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;aACvC,IAAI,CAAC,GAAG,EAAE;YACT,OAAO,EAAE,CAAA;QACX,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,CAAC,EAAE;YACT,IAAI,CAAC,YAAY;gBAAE,OAAM;YAEzB,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QAC1B,CAAC,CAAC,CAAA;IACN,CAAC,EACD,CAAC,YAAY,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,CACtC,CAAA;IAED,OAAO,CAAC,KAAK,IAAI,YAAY,EAAE,QAAQ,CAAC,CAAA;AAC1C,CAAC","sourcesContent":["import { useSuspenseQuery } from '@tanstack/react-query'\nimport { noop } from 'lodash'\nimport { useCallback } from 'react'\nimport { StorageAdapter } from '../utils/native_adapters'\n\nconst cacheKeyGenerator = (key: string) => [`StorageResource:${key}`]\n\ntype SetValue<TCacheData> = (_itemValue?: TCacheData | null) => Promise<any>\n\n/**\n * Hook for using a storage adapter with React Query caching.\n * Similar to useAsyncStorage but accepts a StorageAdapter instead of using AsyncStorage directly.\n */\nexport function useStorage<TCacheData>(\n storage: StorageAdapter,\n key: string,\n initialValue: TCacheData,\n throwOnError: boolean = false\n): [TCacheData, SetValue<TCacheData>] {\n const cacheKey = cacheKeyGenerator(key)\n\n const { data: value, refetch } = useSuspenseQuery<TCacheData>({\n queryKey: cacheKey,\n queryFn: () =>\n storage\n .getItem(key)\n .then(storedValue => {\n if (!storedValue) return initialValue\n\n try {\n return JSON.parse(storedValue)\n } catch {\n return storedValue\n }\n })\n .catch(e => {\n if (!throwOnError) return initialValue\n\n return Promise.reject(e)\n }),\n })\n\n const setValue: SetValue<TCacheData> = useCallback(\n itemValue => {\n if (itemValue === null || itemValue === undefined) {\n return storage\n .removeItem(key)\n .then(() => {\n refetch()\n })\n .catch(noop)\n }\n\n return storage\n .setItem(key, JSON.stringify(itemValue))\n .then(() => {\n refetch()\n })\n .catch(e => {\n if (!throwOnError) return\n\n return Promise.reject(e)\n })\n },\n [throwOnError, key, refetch, storage]\n )\n\n return [value || initialValue, setValue]\n}\n"]}
1
+ {"version":3,"file":"use_storage.js","sourceRoot":"","sources":["../../src/hooks/use_storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AAGnC,MAAM,iBAAiB,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,CAAC,mBAAmB,GAAG,EAAE,CAAC,CAAA;AAIrE;;;GAGG;AACH,MAAM,UAAU,UAAU,CACxB,OAAuB,EACvB,GAAW,EACX,YAAwB,EACxB,eAAwB,KAAK;IAE7B,MAAM,QAAQ,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAA;IAEvC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,gBAAgB,CAAa;QAC5D,QAAQ,EAAE,QAAQ;QAClB,OAAO,EAAE,GAAG,EAAE,CACZ,OAAO;aACJ,OAAO,CAAC,GAAG,CAAC;aACZ,IAAI,CAAC,WAAW,CAAC,EAAE;YAClB,IAAI,CAAC,WAAW;gBAAE,OAAO,YAAY,CAAA;YAErC,IAAI,CAAC;gBACH,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAe,CAAA;YAC9C,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,WAAyB,CAAA;YAClC,CAAC;QACH,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,CAAC,EAAE;YACT,IAAI,CAAC,YAAY;gBAAE,OAAO,YAAY,CAAA;YAEtC,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QAC1B,CAAC,CAAC;KACP,CAAC,CAAA;IAEF,MAAM,QAAQ,GAAyB,WAAW,CAChD,SAAS,CAAC,EAAE;QACV,IAAI,SAAS,KAAK,IAAI,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAClD,OAAO,OAAO;iBACX,UAAU,CAAC,GAAG,CAAC;iBACf,IAAI,CAAC,GAAG,EAAE;gBACT,OAAO,EAAE,CAAA;YACX,CAAC,CAAC;iBACD,KAAK,CAAC,IAAI,CAAC,CAAA;QAChB,CAAC;QAED,OAAO,OAAO;aACX,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;aACvC,IAAI,CAAC,GAAG,EAAE;YACT,OAAO,EAAE,CAAA;QACX,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,CAAC,EAAE;YACT,IAAI,CAAC,YAAY;gBAAE,OAAM;YAEzB,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QAC1B,CAAC,CAAC,CAAA;IACN,CAAC,EACD,CAAC,YAAY,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,CACtC,CAAA;IAED,OAAO,CAAC,KAAK,IAAI,YAAY,EAAE,QAAQ,CAAC,CAAA;AAC1C,CAAC","sourcesContent":["import { useSuspenseQuery } from '@tanstack/react-query'\nimport { noop } from 'lodash'\nimport { useCallback } from 'react'\nimport { StorageAdapter } from '../utils/native_adapters'\n\nconst cacheKeyGenerator = (key: string) => [`StorageResource:${key}`]\n\ntype SetValue<TCacheData> = (_itemValue?: TCacheData | null) => Promise<any>\n\n/**\n * Hook for using a storage adapter with React Query caching.\n * Similar to useAsyncStorage but accepts a StorageAdapter instead of using AsyncStorage directly.\n */\nexport function useStorage<TCacheData>(\n storage: StorageAdapter,\n key: string,\n initialValue: TCacheData,\n throwOnError: boolean = false\n): [TCacheData, SetValue<TCacheData>] {\n const cacheKey = cacheKeyGenerator(key)\n\n const { data: value, refetch } = useSuspenseQuery<TCacheData>({\n queryKey: cacheKey,\n queryFn: () =>\n storage\n .getItem(key)\n .then(storedValue => {\n if (!storedValue) return initialValue\n\n try {\n return JSON.parse(storedValue) as TCacheData\n } catch {\n return storedValue as TCacheData\n }\n })\n .catch(e => {\n if (!throwOnError) return initialValue\n\n return Promise.reject(e)\n }),\n })\n\n const setValue: SetValue<TCacheData> = useCallback(\n itemValue => {\n if (itemValue === null || itemValue === undefined) {\n return storage\n .removeItem(key)\n .then(() => {\n refetch()\n })\n .catch(noop)\n }\n\n return storage\n .setItem(key, JSON.stringify(itemValue))\n .then(() => {\n refetch()\n })\n .catch(e => {\n if (!throwOnError) return\n\n return Promise.reject(e)\n })\n },\n [throwOnError, key, refetch, storage]\n )\n\n return [value || initialValue, setValue]\n}\n"]}
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ import type { PressableProps } from 'react-native';
3
+ import { type IconString } from '../../../components/display/icon';
4
+ interface ListHeaderActionButtonProps extends PressableProps {
5
+ /**
6
+ * Provides context to screen readers about what the button does.
7
+ */
8
+ accessibilityLabel: string;
9
+ /**
10
+ * Specifies the maximum size a font can reach when allowFontScaling is enabled.
11
+ */
12
+ maxFontSizeMultiplier?: number;
13
+ /**
14
+ * Generates an icon from `@planningcenter/icons`
15
+ */
16
+ name: IconString;
17
+ }
18
+ export declare function ListHeaderActionButton({ accessibilityLabel, maxFontSizeMultiplier, name, ...props }: ListHeaderActionButtonProps): React.JSX.Element;
19
+ export {};
20
+ //# sourceMappingURL=list_header_action_button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list_header_action_button.d.ts","sourceRoot":"","sources":["../../../../src/screens/conversations/components/list_header_action_button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAClD,OAAO,EAAQ,KAAK,UAAU,EAAE,MAAM,kCAAkC,CAAA;AAKxE,UAAU,2BAA4B,SAAQ,cAAc;IAC1D;;OAEG;IACH,kBAAkB,EAAE,MAAM,CAAA;IAC1B;;OAEG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B;;OAEG;IACH,IAAI,EAAE,UAAU,CAAA;CACjB;AAED,wBAAgB,sBAAsB,CAAC,EACrC,kBAAkB,EAClB,qBAAqB,EACrB,IAAI,EACJ,GAAG,KAAK,EACT,EAAE,2BAA2B,qBAsB7B"}
@@ -0,0 +1,44 @@
1
+ import React from 'react';
2
+ import { Pressable, StyleSheet } from 'react-native';
3
+ import { Icon } from '../../../components/display/icon';
4
+ import { useTheme, useFontScale, useCreateAndroidRippleColor } from '../../../hooks';
5
+ import { platformPressedOpacityStyle } from '../../../utils';
6
+ import { tokens } from '../../../vendor/tapestry/tokens';
7
+ export function ListHeaderActionButton({ accessibilityLabel, maxFontSizeMultiplier, name, ...props }) {
8
+ const styles = useStyles({ maxFontSizeMultiplier });
9
+ const { colors } = useTheme();
10
+ const androidRippleColor = useCreateAndroidRippleColor({
11
+ color: colors.iconColorDefaultSecondary,
12
+ });
13
+ return (<Pressable style={({ pressed }) => [styles.pressable, pressed && platformPressedOpacityStyle]} accessibilityRole="button" accessibilityLabel={accessibilityLabel} android_ripple={{
14
+ color: androidRippleColor,
15
+ borderless: false,
16
+ foreground: true,
17
+ }} {...props}>
18
+ <Icon name={name} style={styles.icon} maxFontSizeMultiplier={maxFontSizeMultiplier}/>
19
+ </Pressable>);
20
+ }
21
+ const useStyles = ({ maxFontSizeMultiplier }) => {
22
+ const { colors, button } = useTheme();
23
+ const fontScale = useFontScale({ maxFontSizeMultiplier });
24
+ return StyleSheet.create({
25
+ pressable: {
26
+ borderRadius: button.borderRadius * fontScale,
27
+ borderWidth: 1,
28
+ borderColor: colors.borderColorDefaultBase,
29
+ backgroundColor: 'transparent',
30
+ paddingHorizontal: 16 * fontScale,
31
+ flexDirection: 'row',
32
+ alignItems: 'center',
33
+ justifyContent: 'center',
34
+ height: 32 * fontScale,
35
+ gap: 6 * fontScale,
36
+ overflow: 'hidden',
37
+ },
38
+ icon: {
39
+ fontSize: tokens.fontSizeSm * fontScale,
40
+ color: colors.iconColorDefaultSecondary,
41
+ },
42
+ });
43
+ };
44
+ //# sourceMappingURL=list_header_action_button.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list_header_action_button.js","sourceRoot":"","sources":["../../../../src/screens/conversations/components/list_header_action_button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAEpD,OAAO,EAAE,IAAI,EAAmB,MAAM,kCAAkC,CAAA;AACxE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,2BAA2B,EAAE,MAAM,gBAAgB,CAAA;AACpF,OAAO,EAAE,2BAA2B,EAAE,MAAM,gBAAgB,CAAA;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,iCAAiC,CAAA;AAiBxD,MAAM,UAAU,sBAAsB,CAAC,EACrC,kBAAkB,EAClB,qBAAqB,EACrB,IAAI,EACJ,GAAG,KAAK,EACoB;IAC5B,MAAM,MAAM,GAAG,SAAS,CAAC,EAAE,qBAAqB,EAAE,CAAC,CAAA;IACnD,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAA;IAC7B,MAAM,kBAAkB,GAAG,2BAA2B,CAAC;QACrD,KAAK,EAAE,MAAM,CAAC,yBAAyB;KACxC,CAAC,CAAA;IAEF,OAAO,CACL,CAAC,SAAS,CACR,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,IAAI,2BAA2B,CAAC,CAAC,CACnF,iBAAiB,CAAC,QAAQ,CAC1B,kBAAkB,CAAC,CAAC,kBAAkB,CAAC,CACvC,cAAc,CAAC,CAAC;YACd,KAAK,EAAE,kBAAkB;YACzB,UAAU,EAAE,KAAK;YACjB,UAAU,EAAE,IAAI;SACjB,CAAC,CACF,IAAI,KAAK,CAAC,CAEV;MAAA,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,qBAAqB,CAAC,CAAC,qBAAqB,CAAC,EACrF;IAAA,EAAE,SAAS,CAAC,CACb,CAAA;AACH,CAAC;AAED,MAAM,SAAS,GAAG,CAAC,EAAE,qBAAqB,EAAwC,EAAE,EAAE;IACpF,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAA;IACrC,MAAM,SAAS,GAAG,YAAY,CAAC,EAAE,qBAAqB,EAAE,CAAC,CAAA;IAEzD,OAAO,UAAU,CAAC,MAAM,CAAC;QACvB,SAAS,EAAE;YACT,YAAY,EAAE,MAAM,CAAC,YAAY,GAAG,SAAS;YAC7C,WAAW,EAAE,CAAC;YACd,WAAW,EAAE,MAAM,CAAC,sBAAsB;YAC1C,eAAe,EAAE,aAAa;YAC9B,iBAAiB,EAAE,EAAE,GAAG,SAAS;YACjC,aAAa,EAAE,KAAK;YACpB,UAAU,EAAE,QAAQ;YACpB,cAAc,EAAE,QAAQ;YACxB,MAAM,EAAE,EAAE,GAAG,SAAS;YACtB,GAAG,EAAE,CAAC,GAAG,SAAS;YAClB,QAAQ,EAAE,QAAQ;SACnB;QACD,IAAI,EAAE;YACJ,QAAQ,EAAE,MAAM,CAAC,UAAU,GAAG,SAAS;YACvC,KAAK,EAAE,MAAM,CAAC,yBAAyB;SACxC;KACF,CAAC,CAAA;AACJ,CAAC,CAAA","sourcesContent":["import React from 'react'\nimport { Pressable, StyleSheet } from 'react-native'\nimport type { PressableProps } from 'react-native'\nimport { Icon, type IconString } from '../../../components/display/icon'\nimport { useTheme, useFontScale, useCreateAndroidRippleColor } from '../../../hooks'\nimport { platformPressedOpacityStyle } from '../../../utils'\nimport { tokens } from '../../../vendor/tapestry/tokens'\n\ninterface ListHeaderActionButtonProps extends PressableProps {\n /**\n * Provides context to screen readers about what the button does.\n */\n accessibilityLabel: string\n /**\n * Specifies the maximum size a font can reach when allowFontScaling is enabled.\n */\n maxFontSizeMultiplier?: number\n /**\n * Generates an icon from `@planningcenter/icons`\n */\n name: IconString\n}\n\nexport function ListHeaderActionButton({\n accessibilityLabel,\n maxFontSizeMultiplier,\n name,\n ...props\n}: ListHeaderActionButtonProps) {\n const styles = useStyles({ maxFontSizeMultiplier })\n const { colors } = useTheme()\n const androidRippleColor = useCreateAndroidRippleColor({\n color: colors.iconColorDefaultSecondary,\n })\n\n return (\n <Pressable\n style={({ pressed }) => [styles.pressable, pressed && platformPressedOpacityStyle]}\n accessibilityRole=\"button\"\n accessibilityLabel={accessibilityLabel}\n android_ripple={{\n color: androidRippleColor,\n borderless: false,\n foreground: true,\n }}\n {...props}\n >\n <Icon name={name} style={styles.icon} maxFontSizeMultiplier={maxFontSizeMultiplier} />\n </Pressable>\n )\n}\n\nconst useStyles = ({ maxFontSizeMultiplier }: Partial<ListHeaderActionButtonProps>) => {\n const { colors, button } = useTheme()\n const fontScale = useFontScale({ maxFontSizeMultiplier })\n\n return StyleSheet.create({\n pressable: {\n borderRadius: button.borderRadius * fontScale,\n borderWidth: 1,\n borderColor: colors.borderColorDefaultBase,\n backgroundColor: 'transparent',\n paddingHorizontal: 16 * fontScale,\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'center',\n height: 32 * fontScale,\n gap: 6 * fontScale,\n overflow: 'hidden',\n },\n icon: {\n fontSize: tokens.fontSizeSm * fontScale,\n color: colors.iconColorDefaultSecondary,\n },\n })\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"list_header_component.d.ts","sourceRoot":"","sources":["../../../../src/screens/conversations/components/list_header_component.tsx"],"names":[],"mappings":"AACA,OAAO,KAA+B,MAAM,OAAO,CAAA;AAoBnD,eAAO,MAAM,mBAAmB,yBAmH/B,CAAA"}
1
+ {"version":3,"file":"list_header_component.d.ts","sourceRoot":"","sources":["../../../../src/screens/conversations/components/list_header_component.tsx"],"names":[],"mappings":"AACA,OAAO,KAA+B,MAAM,OAAO,CAAA;AAuBnD,eAAO,MAAM,mBAAmB,yBAuJ/B,CAAA"}