@dhis2/app-service-offline 2.10.0 → 2.12.0
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/build/cjs/__tests__/integration.test.js +337 -0
- package/build/cjs/index.js +39 -1
- package/build/cjs/lib/__tests__/clear-sensitive-caches.test.js +131 -0
- package/build/cjs/lib/__tests__/offline-provider.test.js +127 -0
- package/build/cjs/lib/__tests__/use-cacheable-section.test.js +227 -0
- package/build/cjs/lib/cacheable-section-state.js +218 -0
- package/build/cjs/lib/cacheable-section.js +156 -0
- package/build/cjs/lib/clear-sensitive-caches.js +87 -0
- package/build/cjs/lib/global-state-service.js +95 -0
- package/build/cjs/lib/offline-interface.js +86 -0
- package/build/cjs/lib/offline-provider.js +53 -0
- package/build/cjs/types.js +0 -1
- package/build/cjs/utils/__tests__/render-counter.test.js +55 -0
- package/build/cjs/utils/render-counter.js +26 -0
- package/build/cjs/utils/test-mocks.js +40 -0
- package/build/es/__tests__/integration.test.js +327 -0
- package/build/es/index.js +5 -1
- package/build/es/lib/__tests__/clear-sensitive-caches.test.js +123 -0
- package/build/es/lib/__tests__/offline-provider.test.js +117 -0
- package/build/es/lib/__tests__/use-cacheable-section.test.js +218 -0
- package/build/es/lib/cacheable-section-state.js +199 -0
- package/build/es/lib/cacheable-section.js +137 -0
- package/build/es/lib/clear-sensitive-caches.js +78 -0
- package/build/es/lib/global-state-service.js +70 -0
- package/build/es/lib/offline-interface.js +65 -0
- package/build/es/lib/offline-provider.js +40 -0
- package/build/es/types.js +0 -1
- package/build/es/utils/__tests__/render-counter.test.js +40 -0
- package/build/es/utils/render-counter.js +11 -0
- package/build/es/utils/test-mocks.js +30 -0
- package/build/types/index.d.ts +4 -0
- package/build/types/lib/cacheable-section-state.d.ts +66 -0
- package/build/types/lib/cacheable-section.d.ts +52 -0
- package/build/types/lib/clear-sensitive-caches.d.ts +16 -0
- package/build/types/lib/global-state-service.d.ts +16 -0
- package/build/types/lib/offline-interface.d.ts +26 -0
- package/build/types/lib/offline-provider.d.ts +19 -0
- package/build/types/types.d.ts +50 -0
- package/build/types/utils/render-counter.d.ts +10 -0
- package/build/types/utils/test-mocks.d.ts +11 -0
- package/package.json +2 -2
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { useAlert } from '@dhis2/app-service-alerts';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import React, { createContext, useContext } from 'react';
|
|
4
|
+
// This is to prevent 'offlineInterface could be null' type-checking errors
|
|
5
|
+
const noopOfflineInterface = {
|
|
6
|
+
pwaEnabled: false,
|
|
7
|
+
init: () => () => null,
|
|
8
|
+
startRecording: async () => undefined,
|
|
9
|
+
getCachedSections: async () => [],
|
|
10
|
+
removeSection: async () => false
|
|
11
|
+
};
|
|
12
|
+
const OfflineInterfaceContext = /*#__PURE__*/createContext(noopOfflineInterface);
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Receives an OfflineInterface instance as a prop (presumably from the app
|
|
16
|
+
* adapter) and provides it as context for other offline tools.
|
|
17
|
+
*
|
|
18
|
+
* On mount, it initializes the offline interface, which (among other things)
|
|
19
|
+
* checks for service worker updates and, if updates are ready, prompts the
|
|
20
|
+
* user with an alert to skip waiting and reload the page to use new content.
|
|
21
|
+
*/
|
|
22
|
+
export function OfflineInterfaceProvider({
|
|
23
|
+
offlineInterface,
|
|
24
|
+
children
|
|
25
|
+
}) {
|
|
26
|
+
const {
|
|
27
|
+
show
|
|
28
|
+
} = useAlert(({
|
|
29
|
+
message
|
|
30
|
+
}) => message, ({
|
|
31
|
+
action,
|
|
32
|
+
onConfirm
|
|
33
|
+
}) => ({
|
|
34
|
+
actions: [{
|
|
35
|
+
label: action,
|
|
36
|
+
onClick: onConfirm
|
|
37
|
+
}],
|
|
38
|
+
permanent: true
|
|
39
|
+
}));
|
|
40
|
+
React.useEffect(() => {
|
|
41
|
+
// Init returns a tear-down function
|
|
42
|
+
return offlineInterface.init({
|
|
43
|
+
promptUpdate: show
|
|
44
|
+
});
|
|
45
|
+
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
46
|
+
|
|
47
|
+
return /*#__PURE__*/React.createElement(OfflineInterfaceContext.Provider, {
|
|
48
|
+
value: offlineInterface
|
|
49
|
+
}, children);
|
|
50
|
+
}
|
|
51
|
+
OfflineInterfaceProvider.propTypes = {
|
|
52
|
+
children: PropTypes.node,
|
|
53
|
+
offlineInterface: PropTypes.shape({
|
|
54
|
+
init: PropTypes.func
|
|
55
|
+
})
|
|
56
|
+
};
|
|
57
|
+
export function useOfflineInterface() {
|
|
58
|
+
const offlineInterface = useContext(OfflineInterfaceContext);
|
|
59
|
+
|
|
60
|
+
if (offlineInterface === undefined) {
|
|
61
|
+
throw new Error('Offline interface context not found. If this app is using the app platform, make sure `pwa: { enabled: true }` is in d2.config.js. If this is not a platform app, make sure your app is wrapped with an app-runtime <Provider> or an <OfflineProvider> from app-service-offline.');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return offlineInterface;
|
|
65
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import PropTypes from 'prop-types';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { CacheableSectionProvider } from './cacheable-section-state';
|
|
4
|
+
import { OfflineInterfaceProvider } from './offline-interface';
|
|
5
|
+
|
|
6
|
+
/** A context provider for all the relevant offline contexts */
|
|
7
|
+
export function OfflineProvider({
|
|
8
|
+
offlineInterface,
|
|
9
|
+
children
|
|
10
|
+
}) {
|
|
11
|
+
// If an offline interface is not provided, or if one is provided and PWA
|
|
12
|
+
// is not enabled, skip adding context providers
|
|
13
|
+
if (!offlineInterface) {
|
|
14
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, children);
|
|
15
|
+
} // If PWA is not enabled, just init interface to make sure new SW gets
|
|
16
|
+
// activated with code that unregisters SW. Not technically necessary if a
|
|
17
|
+
// killswitch SW takes over, but the killswitch may not always be in use.
|
|
18
|
+
// Then, skip adding any context
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
if (!offlineInterface.pwaEnabled) {
|
|
22
|
+
offlineInterface.init({
|
|
23
|
+
promptUpdate: ({
|
|
24
|
+
onConfirm
|
|
25
|
+
}) => onConfirm()
|
|
26
|
+
});
|
|
27
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, children);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return /*#__PURE__*/React.createElement(OfflineInterfaceProvider, {
|
|
31
|
+
offlineInterface: offlineInterface
|
|
32
|
+
}, /*#__PURE__*/React.createElement(CacheableSectionProvider, null, children));
|
|
33
|
+
}
|
|
34
|
+
OfflineProvider.propTypes = {
|
|
35
|
+
children: PropTypes.node,
|
|
36
|
+
offlineInterface: PropTypes.shape({
|
|
37
|
+
init: PropTypes.func,
|
|
38
|
+
pwaEnabled: PropTypes.bool
|
|
39
|
+
})
|
|
40
|
+
};
|
package/build/es/types.js
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
// todo
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { act, fireEvent, render, screen } from '@testing-library/react';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { RenderCounter, resetRenderCounts } from '../render-counter';
|
|
4
|
+
const renderCounts = {};
|
|
5
|
+
export const Rerenderer = () => {
|
|
6
|
+
const [, setState] = React.useState(true);
|
|
7
|
+
|
|
8
|
+
const toggleState = () => setState(prevState => !prevState);
|
|
9
|
+
|
|
10
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("button", {
|
|
11
|
+
onClick: toggleState,
|
|
12
|
+
role: "button"
|
|
13
|
+
}), /*#__PURE__*/React.createElement(RenderCounter, {
|
|
14
|
+
id: 'rc1',
|
|
15
|
+
countsObj: renderCounts
|
|
16
|
+
}));
|
|
17
|
+
};
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
resetRenderCounts(renderCounts);
|
|
20
|
+
});
|
|
21
|
+
it('increments the counter when rerendered', () => {
|
|
22
|
+
render( /*#__PURE__*/React.createElement(Rerenderer, null));
|
|
23
|
+
const {
|
|
24
|
+
getByTestId,
|
|
25
|
+
getByRole
|
|
26
|
+
} = screen;
|
|
27
|
+
expect(getByTestId('rc1')).toHaveTextContent('1');
|
|
28
|
+
act(() => {
|
|
29
|
+
fireEvent.click(getByRole('button'));
|
|
30
|
+
});
|
|
31
|
+
expect(getByTestId('rc1')).toHaveTextContent('2');
|
|
32
|
+
act(() => {
|
|
33
|
+
fireEvent.click(getByRole('button'));
|
|
34
|
+
});
|
|
35
|
+
expect(getByTestId('rc1')).toHaveTextContent('3');
|
|
36
|
+
});
|
|
37
|
+
it('resets the render counter successfully', () => {
|
|
38
|
+
render( /*#__PURE__*/React.createElement(Rerenderer, null));
|
|
39
|
+
expect(screen.getByTestId('rc1')).toHaveTextContent('1');
|
|
40
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export const RenderCounter = ({
|
|
3
|
+
id,
|
|
4
|
+
countsObj
|
|
5
|
+
}) => {
|
|
6
|
+
if (!(id in countsObj)) countsObj[id] = 0;
|
|
7
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
8
|
+
"data-testid": id
|
|
9
|
+
}, ++countsObj[id]);
|
|
10
|
+
};
|
|
11
|
+
export const resetRenderCounts = renderCounts => Object.keys(renderCounts).forEach(key => renderCounts[key] = 0);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export const successfulRecordingMock = jest.fn().mockImplementation(async ({
|
|
2
|
+
onStarted,
|
|
3
|
+
onCompleted
|
|
4
|
+
} = {}) => {
|
|
5
|
+
// in 100ms, call 'onStarted' callback (allows 'pending' state)
|
|
6
|
+
if (onStarted) setTimeout(onStarted, 100); // in 200ms, call 'onCompleted' callback
|
|
7
|
+
|
|
8
|
+
if (onCompleted) setTimeout(onCompleted, 200); // resolve
|
|
9
|
+
|
|
10
|
+
return Promise.resolve();
|
|
11
|
+
});
|
|
12
|
+
export const errorRecordingMock = jest.fn().mockImplementation(({
|
|
13
|
+
onStarted,
|
|
14
|
+
onError
|
|
15
|
+
} = {}) => {
|
|
16
|
+
// in 100ms, call 'onStarted' callback (allows 'pending' state)
|
|
17
|
+
if (onStarted) setTimeout(onStarted, 100); // in 200ms, call 'onError'
|
|
18
|
+
|
|
19
|
+
setTimeout(() => onError(new Error('test err')), 200); // resolve to signal successful initiation
|
|
20
|
+
|
|
21
|
+
return Promise.resolve();
|
|
22
|
+
});
|
|
23
|
+
export const failedMessageRecordingMock = jest.fn().mockRejectedValue(new Error('Failed message'));
|
|
24
|
+
export const mockOfflineInterface = {
|
|
25
|
+
pwaEnabled: true,
|
|
26
|
+
init: jest.fn(),
|
|
27
|
+
startRecording: successfulRecordingMock,
|
|
28
|
+
getCachedSections: jest.fn().mockResolvedValue([]),
|
|
29
|
+
removeSection: jest.fn().mockResolvedValue(true)
|
|
30
|
+
};
|
package/build/types/index.d.ts
CHANGED
|
@@ -1 +1,5 @@
|
|
|
1
|
+
export { OfflineProvider } from './lib/offline-provider';
|
|
2
|
+
export { CacheableSection, useCacheableSection } from './lib/cacheable-section';
|
|
3
|
+
export { useCachedSections } from './lib/cacheable-section-state';
|
|
1
4
|
export { useOnlineStatus } from './lib/online-status';
|
|
5
|
+
export { clearSensitiveCaches } from './lib/clear-sensitive-caches';
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import PropTypes from 'prop-types';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { GlobalStateStore, RecordingState } from '../types';
|
|
4
|
+
interface CachedSectionsById {
|
|
5
|
+
[index: string]: {
|
|
6
|
+
lastUpdated: Date;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Create a store for Cacheable Section state.
|
|
11
|
+
* Expected to be used in app adapter
|
|
12
|
+
*/
|
|
13
|
+
export declare function createCacheableSectionStore(): GlobalStateStore;
|
|
14
|
+
/**
|
|
15
|
+
* Provides context for a global state context which will track cached
|
|
16
|
+
* sections' status and cacheable sections' recording states, which will
|
|
17
|
+
* determine how that component will render. The provider will be a part of
|
|
18
|
+
* the OfflineProvider.
|
|
19
|
+
*/
|
|
20
|
+
export declare function CacheableSectionProvider({ children, }: {
|
|
21
|
+
children: React.ReactNode;
|
|
22
|
+
}): JSX.Element;
|
|
23
|
+
export declare namespace CacheableSectionProvider {
|
|
24
|
+
var propTypes: {
|
|
25
|
+
children: PropTypes.Requireable<PropTypes.ReactNodeLike>;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
interface RecordingStateControls {
|
|
29
|
+
recordingState: RecordingState;
|
|
30
|
+
setRecordingState: (newState: RecordingState) => void;
|
|
31
|
+
removeRecordingState: () => void;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Uses an optimized global state to manage 'recording state' values without
|
|
35
|
+
* unnecessarily rerendering all consuming components
|
|
36
|
+
*
|
|
37
|
+
* @param {String} id - ID of the cacheable section to track
|
|
38
|
+
* @returns {Object} { recordingState: String, setRecordingState: Function, removeRecordingState: Function}
|
|
39
|
+
*/
|
|
40
|
+
export declare function useRecordingState(id: string): RecordingStateControls;
|
|
41
|
+
interface CachedSectionsControls {
|
|
42
|
+
cachedSections: CachedSectionsById;
|
|
43
|
+
removeById: (id: string) => Promise<boolean>;
|
|
44
|
+
syncCachedSections: () => Promise<void>;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Uses global state to manage an object of cached sections' statuses
|
|
48
|
+
*
|
|
49
|
+
* @returns {Object} { cachedSections: Object, removeSection: Function }
|
|
50
|
+
*/
|
|
51
|
+
export declare function useCachedSections(): CachedSectionsControls;
|
|
52
|
+
interface CachedSectionControls {
|
|
53
|
+
lastUpdated: Date;
|
|
54
|
+
isCached: boolean;
|
|
55
|
+
remove: () => Promise<boolean>;
|
|
56
|
+
syncCachedSections: () => Promise<void>;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Uses global state to manage the cached status of just one section, which
|
|
60
|
+
* prevents unnecessary rerenders of consuming components
|
|
61
|
+
*
|
|
62
|
+
* @param {String} id
|
|
63
|
+
* @returns {Object} { lastUpdated: Date, remove: Function }
|
|
64
|
+
*/
|
|
65
|
+
export declare function useCachedSection(id: string): CachedSectionControls;
|
|
66
|
+
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import PropTypes from 'prop-types';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { RecordingState } from '../types';
|
|
4
|
+
interface CacheableSectionStartRecordingOptions {
|
|
5
|
+
recordingTimeoutDelay?: number;
|
|
6
|
+
onStarted?: () => void;
|
|
7
|
+
onCompleted?: () => void;
|
|
8
|
+
onError?: (err: Error) => void;
|
|
9
|
+
}
|
|
10
|
+
export declare type CacheableSectionStartRecording = (options?: CacheableSectionStartRecordingOptions) => Promise<any>;
|
|
11
|
+
interface CacheableSectionControls {
|
|
12
|
+
recordingState: RecordingState;
|
|
13
|
+
startRecording: CacheableSectionStartRecording;
|
|
14
|
+
lastUpdated: Date | undefined;
|
|
15
|
+
isCached: boolean;
|
|
16
|
+
remove: () => Promise<boolean>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Returns the main controls for a cacheable section and manages recording
|
|
20
|
+
* state, which affects the render state of the CacheableSection component.
|
|
21
|
+
* Also returns the cached status of the section, which come straight from
|
|
22
|
+
* the `useCachedSection` hook.
|
|
23
|
+
*
|
|
24
|
+
* @param {String} id
|
|
25
|
+
* @returns {Object}
|
|
26
|
+
*/
|
|
27
|
+
export declare function useCacheableSection(id: string): CacheableSectionControls;
|
|
28
|
+
interface CacheableSectionProps {
|
|
29
|
+
id: string;
|
|
30
|
+
loadingMask: JSX.Element;
|
|
31
|
+
children: React.ReactNode;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Used to wrap the relevant component to be recorded and saved offline.
|
|
35
|
+
* Depending on the recording state of the section, this wrapper will
|
|
36
|
+
* render its children, not render its children while recording is pending,
|
|
37
|
+
* or RErerender the chilren to force data fetching to record by the service
|
|
38
|
+
* worker.
|
|
39
|
+
*
|
|
40
|
+
* During recording, a loading mask provided by props is also rendered that is
|
|
41
|
+
* intended to prevent other interaction with the app that might interfere
|
|
42
|
+
* with the recording process.
|
|
43
|
+
*/
|
|
44
|
+
export declare function CacheableSection({ id, loadingMask, children, }: CacheableSectionProps): JSX.Element;
|
|
45
|
+
export declare namespace CacheableSection {
|
|
46
|
+
var propTypes: {
|
|
47
|
+
id: PropTypes.Validator<string>;
|
|
48
|
+
children: PropTypes.Requireable<PropTypes.ReactNodeLike>;
|
|
49
|
+
loadingMask: PropTypes.Requireable<PropTypes.ReactNodeLike>;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const SECTIONS_DB = "sections-db";
|
|
2
|
+
export declare const SECTIONS_STORE = "sections-store";
|
|
3
|
+
declare global {
|
|
4
|
+
interface IDBFactory {
|
|
5
|
+
databases(): Promise<[{
|
|
6
|
+
name: string;
|
|
7
|
+
version: number;
|
|
8
|
+
}]>;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Used to clear caches and 'sections-db' IndexedDB when a user logs out or a
|
|
13
|
+
* different user logs in to prevent someone from accessing a different user's
|
|
14
|
+
* caches. Should be able to be used in a non-PWA app.
|
|
15
|
+
*/
|
|
16
|
+
export declare function clearSensitiveCaches(dbName?: string): Promise<any>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import PropTypes from 'prop-types';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { GlobalStateStore, GlobalStateStoreMutateMethod, GlobalStateMutation, GlobalStateStoreMutationCreator } from '../types';
|
|
4
|
+
export declare const createStore: (initialState?: {}) => GlobalStateStore;
|
|
5
|
+
export declare const GlobalStateProvider: {
|
|
6
|
+
({ store, children, }: {
|
|
7
|
+
store: GlobalStateStore;
|
|
8
|
+
children: React.ReactNode;
|
|
9
|
+
}): JSX.Element;
|
|
10
|
+
propTypes: {
|
|
11
|
+
children: PropTypes.Requireable<PropTypes.ReactNodeLike>;
|
|
12
|
+
store: PropTypes.Requireable<PropTypes.InferProps<{}>>;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
export declare const useGlobalState: (selector?: (state: any) => any) => [any, GlobalStateStoreMutateMethod];
|
|
16
|
+
export declare function useGlobalStateMutation<Type>(mutationCreator: GlobalStateStoreMutationCreator<Type>): GlobalStateMutation<Type>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import PropTypes from 'prop-types';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { OfflineInterface } from '../types';
|
|
4
|
+
interface OfflineInterfaceProviderInput {
|
|
5
|
+
offlineInterface: OfflineInterface;
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Receives an OfflineInterface instance as a prop (presumably from the app
|
|
10
|
+
* adapter) and provides it as context for other offline tools.
|
|
11
|
+
*
|
|
12
|
+
* On mount, it initializes the offline interface, which (among other things)
|
|
13
|
+
* checks for service worker updates and, if updates are ready, prompts the
|
|
14
|
+
* user with an alert to skip waiting and reload the page to use new content.
|
|
15
|
+
*/
|
|
16
|
+
export declare function OfflineInterfaceProvider({ offlineInterface, children, }: OfflineInterfaceProviderInput): JSX.Element;
|
|
17
|
+
export declare namespace OfflineInterfaceProvider {
|
|
18
|
+
var propTypes: {
|
|
19
|
+
children: PropTypes.Requireable<PropTypes.ReactNodeLike>;
|
|
20
|
+
offlineInterface: PropTypes.Requireable<PropTypes.InferProps<{
|
|
21
|
+
init: PropTypes.Requireable<(...args: any[]) => any>;
|
|
22
|
+
}>>;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export declare function useOfflineInterface(): OfflineInterface;
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import PropTypes from 'prop-types';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { OfflineInterface } from '../types';
|
|
4
|
+
interface OfflineProviderInput {
|
|
5
|
+
offlineInterface?: OfflineInterface;
|
|
6
|
+
children?: React.ReactNode;
|
|
7
|
+
}
|
|
8
|
+
/** A context provider for all the relevant offline contexts */
|
|
9
|
+
export declare function OfflineProvider({ offlineInterface, children, }: OfflineProviderInput): JSX.Element;
|
|
10
|
+
export declare namespace OfflineProvider {
|
|
11
|
+
var propTypes: {
|
|
12
|
+
children: PropTypes.Requireable<PropTypes.ReactNodeLike>;
|
|
13
|
+
offlineInterface: PropTypes.Requireable<PropTypes.InferProps<{
|
|
14
|
+
init: PropTypes.Requireable<(...args: any[]) => any>;
|
|
15
|
+
pwaEnabled: PropTypes.Requireable<boolean>;
|
|
16
|
+
}>>;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export {};
|
package/build/types/types.d.ts
CHANGED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export declare type RecordingState = 'default' | 'pending' | 'error' | 'recording';
|
|
2
|
+
export interface GlobalStateStoreMutation {
|
|
3
|
+
(state: any): any;
|
|
4
|
+
}
|
|
5
|
+
export interface GlobalStateStoreMutationCreator<Type> {
|
|
6
|
+
(...args: Type[]): GlobalStateStoreMutation;
|
|
7
|
+
}
|
|
8
|
+
export interface GlobalStateMutation<Type> {
|
|
9
|
+
(...args: Type[]): void;
|
|
10
|
+
}
|
|
11
|
+
export interface GlobalStateStoreMutateMethod {
|
|
12
|
+
(mutation: GlobalStateStoreMutation): void;
|
|
13
|
+
}
|
|
14
|
+
export interface GlobalStateStore {
|
|
15
|
+
getState: () => any;
|
|
16
|
+
subscribe: (callback: (state: any) => void) => void;
|
|
17
|
+
unsubscribe: (callback: (state: any) => void) => void;
|
|
18
|
+
mutate: GlobalStateStoreMutateMethod;
|
|
19
|
+
}
|
|
20
|
+
interface PromptUpdate {
|
|
21
|
+
(params: {
|
|
22
|
+
message: string;
|
|
23
|
+
action: string;
|
|
24
|
+
onConfirm: () => void;
|
|
25
|
+
}): void;
|
|
26
|
+
}
|
|
27
|
+
interface StartRecording {
|
|
28
|
+
(params: {
|
|
29
|
+
sectionId: string;
|
|
30
|
+
recordingTimeoutDelay: number;
|
|
31
|
+
onStarted: () => void;
|
|
32
|
+
onCompleted: () => void;
|
|
33
|
+
onError: (err: Error) => void;
|
|
34
|
+
}): Promise<undefined>;
|
|
35
|
+
}
|
|
36
|
+
export interface IndexedDBCachedSection {
|
|
37
|
+
sectionId: string;
|
|
38
|
+
lastUpdated: Date;
|
|
39
|
+
requests: number;
|
|
40
|
+
}
|
|
41
|
+
export interface OfflineInterface {
|
|
42
|
+
readonly pwaEnabled: boolean;
|
|
43
|
+
init: (params: {
|
|
44
|
+
promptUpdate: PromptUpdate;
|
|
45
|
+
}) => () => void;
|
|
46
|
+
startRecording: StartRecording;
|
|
47
|
+
getCachedSections: () => Promise<IndexedDBCachedSection[]>;
|
|
48
|
+
removeSection: (id: string) => Promise<boolean>;
|
|
49
|
+
}
|
|
50
|
+
export {};
|