@applicaster/quick-brick-core 16.0.0-rc.31 → 16.0.0-rc.33
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.
|
@@ -3,6 +3,14 @@ import * as R from "ramda";
|
|
|
3
3
|
|
|
4
4
|
import { ActionsContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ActionsContext";
|
|
5
5
|
import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
|
|
6
|
+
import { createLogger } from "@applicaster/zapp-react-native-utils/logger";
|
|
7
|
+
|
|
8
|
+
import { LegacyActionsRegistryAdapter } from "./LegacyActionsRegistryAdapter";
|
|
9
|
+
|
|
10
|
+
const { log_debug } = createLogger({
|
|
11
|
+
subsystem: "ActionsProvider",
|
|
12
|
+
category: "ActionRegistration",
|
|
13
|
+
});
|
|
6
14
|
|
|
7
15
|
type Props = {
|
|
8
16
|
children: React.ReactNode;
|
|
@@ -36,19 +44,17 @@ const abstractIdentifier = (actionPlugins: Plugin[]): PluginsIdMap =>
|
|
|
36
44
|
* Component returning children.
|
|
37
45
|
* Can be used to create Component from children
|
|
38
46
|
*/
|
|
39
|
-
const ChildrenWrapper = ({
|
|
40
|
-
children
|
|
41
|
-
}: {
|
|
42
|
-
children: React.ReactElement<any>;
|
|
43
|
-
}) => {
|
|
44
|
-
return children;
|
|
47
|
+
const ChildrenWrapper = ({ children }: { children: React.ReactNode }) => {
|
|
48
|
+
return <>{children}</>;
|
|
45
49
|
};
|
|
46
50
|
|
|
47
51
|
/**
|
|
48
52
|
* It wraps children in multiple context providers
|
|
49
53
|
* @param contexts - Array of React Context Providers
|
|
50
54
|
*/
|
|
51
|
-
const contextComposer = (
|
|
55
|
+
const contextComposer = (
|
|
56
|
+
contexts: Plugin[]
|
|
57
|
+
): React.ComponentType<React.PropsWithChildren> =>
|
|
52
58
|
R.compose(...contexts)(ChildrenWrapper);
|
|
53
59
|
|
|
54
60
|
/**
|
|
@@ -69,6 +75,19 @@ export function ActionsProvider(props: Props) {
|
|
|
69
75
|
[plugins]
|
|
70
76
|
);
|
|
71
77
|
|
|
78
|
+
React.useEffect(() => {
|
|
79
|
+
const count = Object.keys(actionPlugins).length;
|
|
80
|
+
|
|
81
|
+
if (count > 0) {
|
|
82
|
+
log_debug(
|
|
83
|
+
`ActionsProvider: composed ${count} action plugin(s) into context`,
|
|
84
|
+
{ identifiers: Object.keys(actionPlugins) }
|
|
85
|
+
);
|
|
86
|
+
} else {
|
|
87
|
+
log_debug("ActionsProvider: no action plugins to compose");
|
|
88
|
+
}
|
|
89
|
+
}, [actionPlugins]);
|
|
90
|
+
|
|
72
91
|
const contextProviders = React.useMemo((): [Plugin] | [] => {
|
|
73
92
|
try {
|
|
74
93
|
const providers = R.compose(
|
|
@@ -88,7 +107,7 @@ export function ActionsProvider(props: Props) {
|
|
|
88
107
|
? contextComposer(contextProviders)
|
|
89
108
|
: React.Fragment,
|
|
90
109
|
[]
|
|
91
|
-
)
|
|
110
|
+
) as React.ComponentType<React.PropsWithChildren>;
|
|
92
111
|
|
|
93
112
|
const contextValue = React.useMemo(
|
|
94
113
|
() => ({ actions: actionPlugins }),
|
|
@@ -97,7 +116,10 @@ export function ActionsProvider(props: Props) {
|
|
|
97
116
|
|
|
98
117
|
return (
|
|
99
118
|
<ActionsContext.Provider value={contextValue}>
|
|
100
|
-
<Context>
|
|
119
|
+
<Context>
|
|
120
|
+
<LegacyActionsRegistryAdapter actionPlugins={actionPlugins} />
|
|
121
|
+
{children}
|
|
122
|
+
</Context>
|
|
101
123
|
</ActionsContext.Provider>
|
|
102
124
|
);
|
|
103
125
|
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as R from "ramda";
|
|
3
|
+
|
|
4
|
+
import { uiActionsRegistry } from "@applicaster/zapp-react-native-utils/uiActionsRegistrator";
|
|
5
|
+
import { createLogger } from "@applicaster/zapp-react-native-utils/logger";
|
|
6
|
+
|
|
7
|
+
const { log_debug, log_warning } = createLogger({
|
|
8
|
+
subsystem: "LegacyActionsRegistryAdapter",
|
|
9
|
+
category: "ActionRegistration",
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
type LegacyActionPlugin = Record<string, any> & {
|
|
13
|
+
identifier: string;
|
|
14
|
+
module: {
|
|
15
|
+
context?: React.Context<any>;
|
|
16
|
+
[key: string]: any;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Bridges a single legacy action plugin (one that exposes `module.context`)
|
|
22
|
+
* into the `uiActionsRegistry`.
|
|
23
|
+
*
|
|
24
|
+
* Reactivity note: legacy stateful actions rely on React Context re-renders to
|
|
25
|
+
* propagate their latest value to subscribed UI (via `useActions`). We keep
|
|
26
|
+
* that mechanism intact and only *mirror* the current value into the registry
|
|
27
|
+
* through a ref, so registry-based consumers always read the freshest value at
|
|
28
|
+
* call time without changing legacy reactivity.
|
|
29
|
+
*/
|
|
30
|
+
function LegacyActionBridge({ plugin }: { plugin: LegacyActionPlugin }) {
|
|
31
|
+
// `plugin.module.context` is stable for the lifetime of the plugin, so this
|
|
32
|
+
// single `useContext` call is safe and rules-of-hooks compliant.
|
|
33
|
+
const value = React.useContext(plugin.module.context as React.Context<any>);
|
|
34
|
+
|
|
35
|
+
const valueRef = React.useRef(value);
|
|
36
|
+
valueRef.current = value;
|
|
37
|
+
|
|
38
|
+
React.useEffect(() => {
|
|
39
|
+
if (value == null) {
|
|
40
|
+
log_warning(
|
|
41
|
+
`LegacyActionBridge: context value for "${plugin.identifier}" is null/undefined – skipping registration`,
|
|
42
|
+
{ identifier: plugin.identifier }
|
|
43
|
+
);
|
|
44
|
+
} else {
|
|
45
|
+
log_debug(
|
|
46
|
+
`LegacyActionBridge: context value ready for "${plugin.identifier}", registering in UIActionsRegistry`,
|
|
47
|
+
{ identifier: plugin.identifier }
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const unregister = uiActionsRegistry.registerActionProvider(
|
|
52
|
+
plugin.identifier,
|
|
53
|
+
() =>
|
|
54
|
+
valueRef.current
|
|
55
|
+
? [{ identifier: plugin.identifier, action: valueRef.current }]
|
|
56
|
+
: []
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
return () => {
|
|
60
|
+
log_debug(
|
|
61
|
+
`LegacyActionBridge: unmounting bridge for "${plugin.identifier}"`,
|
|
62
|
+
{ identifier: plugin.identifier }
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
unregister();
|
|
66
|
+
};
|
|
67
|
+
}, [plugin.identifier]);
|
|
68
|
+
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
type Props = {
|
|
73
|
+
actionPlugins: Record<string, LegacyActionPlugin>;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Registers every legacy action plugin's live context value into the
|
|
78
|
+
* `uiActionsRegistry`. It must be rendered *inside* the composed context
|
|
79
|
+
* providers (see `ActionsProvider`) so that each plugin's context is populated.
|
|
80
|
+
*
|
|
81
|
+
* This is the compatibility layer that lets new, registry-based consumers read
|
|
82
|
+
* actions coming from old plugins that still export `contextProvider`/`context`.
|
|
83
|
+
*/
|
|
84
|
+
export function LegacyActionsRegistryAdapter({ actionPlugins }: Props) {
|
|
85
|
+
const bridgedPlugins = React.useMemo(
|
|
86
|
+
() =>
|
|
87
|
+
R.values(actionPlugins).filter(
|
|
88
|
+
(plugin) => plugin?.module?.context != null
|
|
89
|
+
),
|
|
90
|
+
[actionPlugins]
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
log_debug(
|
|
94
|
+
`LegacyActionsRegistryAdapter: bridging ${bridgedPlugins.length} legacy action plugin(s)`,
|
|
95
|
+
{ identifiers: bridgedPlugins.map((p) => p.identifier) }
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
return (
|
|
99
|
+
<>
|
|
100
|
+
{bridgedPlugins.map((plugin) => (
|
|
101
|
+
<LegacyActionBridge key={plugin.identifier} plugin={plugin} />
|
|
102
|
+
))}
|
|
103
|
+
</>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
LegacyActionsRegistryAdapter.displayName = "LegacyActionsRegistryAdapter";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/quick-brick-core",
|
|
3
|
-
"version": "16.0.0-rc.
|
|
3
|
+
"version": "16.0.0-rc.33",
|
|
4
4
|
"description": "Core package for Applicaster's Quick Brick App",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -28,13 +28,13 @@
|
|
|
28
28
|
},
|
|
29
29
|
"homepage": "https://github.com/applicaster/quickbrick#readme",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@applicaster/applicaster-types": "16.0.0-rc.
|
|
32
|
-
"@applicaster/quick-brick-core-plugins": "16.0.0-rc.
|
|
33
|
-
"@applicaster/zapp-pipes-v2-client": "16.0.0-rc.
|
|
34
|
-
"@applicaster/zapp-react-native-bridge": "16.0.0-rc.
|
|
35
|
-
"@applicaster/zapp-react-native-redux": "16.0.0-rc.
|
|
36
|
-
"@applicaster/zapp-react-native-ui-components": "16.0.0-rc.
|
|
37
|
-
"@applicaster/zapp-react-native-utils": "16.0.0-rc.
|
|
31
|
+
"@applicaster/applicaster-types": "16.0.0-rc.33",
|
|
32
|
+
"@applicaster/quick-brick-core-plugins": "16.0.0-rc.33",
|
|
33
|
+
"@applicaster/zapp-pipes-v2-client": "16.0.0-rc.33",
|
|
34
|
+
"@applicaster/zapp-react-native-bridge": "16.0.0-rc.33",
|
|
35
|
+
"@applicaster/zapp-react-native-redux": "16.0.0-rc.33",
|
|
36
|
+
"@applicaster/zapp-react-native-ui-components": "16.0.0-rc.33",
|
|
37
|
+
"@applicaster/zapp-react-native-utils": "16.0.0-rc.33",
|
|
38
38
|
"atob": "^2.1.2",
|
|
39
39
|
"axios": "^0.28.0",
|
|
40
40
|
"btoa": "^1.2.1",
|