@applicaster/zapp-react-native-utils 16.0.0-rc.72 → 16.0.0-rc.74
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.
|
@@ -135,7 +135,8 @@ function generateFieldsFromDefaults(label, defaults, fields) {
|
|
|
135
135
|
function generateFieldsFromDefaultsWithoutPrefixedLabel(
|
|
136
136
|
label,
|
|
137
137
|
defaults,
|
|
138
|
-
fields
|
|
138
|
+
fields,
|
|
139
|
+
{ withStyle = false } = {}
|
|
139
140
|
) {
|
|
140
141
|
const keyPrefix = toSnakeCase(label);
|
|
141
142
|
|
|
@@ -151,7 +152,9 @@ function generateFieldsFromDefaultsWithoutPrefixedLabel(
|
|
|
151
152
|
const generatedField = {
|
|
152
153
|
...fieldProps,
|
|
153
154
|
label: capitalizeFirstLetter(field.suffix),
|
|
154
|
-
key:
|
|
155
|
+
key: withStyle
|
|
156
|
+
? `${keyPrefix}_style_${toSnakeCase(field.suffix)}`
|
|
157
|
+
: `${keyPrefix}_${toSnakeCase(field.suffix)}`,
|
|
155
158
|
initial_value: R.when(R.is(Array), R.head)(initialValue),
|
|
156
159
|
};
|
|
157
160
|
|
|
@@ -164,7 +167,9 @@ function generateFieldsFromDefaultsWithoutPrefixedLabel(
|
|
|
164
167
|
const section = condition.section ? `${condition.section}/` : "";
|
|
165
168
|
|
|
166
169
|
return {
|
|
167
|
-
key:
|
|
170
|
+
key: withStyle
|
|
171
|
+
? `${section}${keyPrefix}_style_${toSnakeCase(condition.key)}`
|
|
172
|
+
: `${section}${keyPrefix}_${toSnakeCase(condition.key)}`,
|
|
168
173
|
condition_value: condition.value,
|
|
169
174
|
};
|
|
170
175
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/zapp-react-native-utils",
|
|
3
|
-
"version": "16.0.0-rc.
|
|
3
|
+
"version": "16.0.0-rc.74",
|
|
4
4
|
"description": "Applicaster Zapp React Native utilities package",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"homepage": "https://github.com/applicaster/quickbrick#readme",
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@applicaster/applicaster-types": "16.0.0-rc.
|
|
30
|
+
"@applicaster/applicaster-types": "16.0.0-rc.74",
|
|
31
31
|
"buffer": "^5.2.1",
|
|
32
32
|
"camelize": "^1.0.0",
|
|
33
33
|
"dayjs": "^1.11.10",
|
|
@@ -87,7 +87,31 @@ export function useEntryActionState(
|
|
|
87
87
|
useEffect(() => {
|
|
88
88
|
if (!action) return undefined;
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
// An action's stream is third-party code. Subscribing with only a `next`
|
|
91
|
+
// handler lets RxJS rethrow an error notification asynchronously, where no
|
|
92
|
+
// error boundary catches it - one plugin faulting would take the app down
|
|
93
|
+
// rather than this one button. The button keeps its last known state.
|
|
94
|
+
let subscription;
|
|
95
|
+
|
|
96
|
+
try {
|
|
97
|
+
subscription = observeEntryState(action, entry).subscribe({
|
|
98
|
+
next: setState,
|
|
99
|
+
error: (error) =>
|
|
100
|
+
logger.warning({
|
|
101
|
+
message:
|
|
102
|
+
"useEntryActionState: the action's state stream failed - the button keeps its last state",
|
|
103
|
+
data: { entryId, error },
|
|
104
|
+
}),
|
|
105
|
+
});
|
|
106
|
+
} catch (error) {
|
|
107
|
+
logger.warning({
|
|
108
|
+
message:
|
|
109
|
+
"useEntryActionState: could not observe the action - the button keeps its initial state",
|
|
110
|
+
data: { entryId, error },
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
91
115
|
|
|
92
116
|
return () => subscription.unsubscribe();
|
|
93
117
|
// eslint-disable-next-line @wogns3623/better-exhaustive-deps/exhaustive-deps
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/* eslint-disable no-dupe-class-members */
|
|
2
|
+
import type { ComponentType } from "react";
|
|
2
3
|
import { Observable } from "rxjs";
|
|
3
4
|
import { createLogger } from "../logger";
|
|
4
5
|
|
|
@@ -119,12 +120,101 @@ export function isActionAvailableFor(
|
|
|
119
120
|
action: RegisteredActionValue | undefined,
|
|
120
121
|
entry: ZappEntry | ZappFeed
|
|
121
122
|
): boolean {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
123
|
+
// The first name the action defines *as a function* answers. Nullish
|
|
124
|
+
// coalescing would let a plugin shipping one of these as a plain flag
|
|
125
|
+
// short-circuit the chain and mask a real predicate behind it.
|
|
126
|
+
const predicate = [
|
|
127
|
+
action?.isSupportDownloads,
|
|
128
|
+
action?.isActionSupported,
|
|
129
|
+
action?.isActionAvailable,
|
|
130
|
+
].find((candidate) => typeof candidate === "function");
|
|
126
131
|
|
|
127
|
-
|
|
132
|
+
if (!predicate) {
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
try {
|
|
137
|
+
return Boolean(predicate(entry));
|
|
138
|
+
} catch (error) {
|
|
139
|
+
// Third-party code, called during render. Showing the action is the
|
|
140
|
+
// recoverable answer: a button that does nothing beats a screen that does
|
|
141
|
+
// not render.
|
|
142
|
+
log_warning(
|
|
143
|
+
"isActionAvailableFor: availability check threw - the action is shown",
|
|
144
|
+
{ entryId: (entry as ZappEntry)?.id, error }
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** How an action's asset should be drawn, or `null` if it cannot be. */
|
|
152
|
+
export type ResolvedActionAsset =
|
|
153
|
+
| { uri: string }
|
|
154
|
+
| { Component: ComponentType<any> }
|
|
155
|
+
| null;
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Interprets `CellActionEntryState["asset"]`.
|
|
159
|
+
*
|
|
160
|
+
* It is either something an image can take - a URI, or a per-flavour array -
|
|
161
|
+
* or a component that draws itself. A plain object is neither: a locale or
|
|
162
|
+
* state map arrives that way, and handing one to JSX throws "Element type is
|
|
163
|
+
* invalid".
|
|
164
|
+
*
|
|
165
|
+
* A React *element* carries the same `$$typeof` marker as a `memo`,
|
|
166
|
+
* `forwardRef` or `lazy` result, so `asset: <Icon/>` where `asset: Icon` was
|
|
167
|
+
* meant would pass a naive check and throw exactly that. Elements are told
|
|
168
|
+
* apart by carrying `props`.
|
|
169
|
+
*
|
|
170
|
+
* One function so that "can this draw?" and "draw it" cannot disagree.
|
|
171
|
+
*/
|
|
172
|
+
export function resolveActionAsset(asset: unknown): ResolvedActionAsset {
|
|
173
|
+
if (typeof asset === "string") {
|
|
174
|
+
return asset.length > 0 ? { uri: asset } : null;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (Array.isArray(asset)) {
|
|
178
|
+
const first = asset.find(
|
|
179
|
+
(candidate) => typeof candidate === "string" && candidate.length > 0
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
return first ? { uri: first as string } : null;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (typeof asset === "function") {
|
|
186
|
+
return { Component: asset as ComponentType<any> };
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (
|
|
190
|
+
typeof asset === "object" &&
|
|
191
|
+
asset !== null &&
|
|
192
|
+
"$$typeof" in asset &&
|
|
193
|
+
!("props" in asset)
|
|
194
|
+
) {
|
|
195
|
+
return { Component: asset as ComponentType<any> };
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Whether the action has something an icon-only button can actually draw.
|
|
203
|
+
*
|
|
204
|
+
* An overlay button is an icon and nothing else, so an action whose state
|
|
205
|
+
* carries no usable asset renders as nothing at all - legal for an entry action
|
|
206
|
+
* declared with a title and no `iconURL`. Surfaces that must keep an action
|
|
207
|
+
* reachable ask this before putting it somewhere it can only appear as an icon.
|
|
208
|
+
*/
|
|
209
|
+
export function canRenderActionIcon(
|
|
210
|
+
action: RegisteredActionValue | undefined,
|
|
211
|
+
entry: ZappEntry | ZappFeed
|
|
212
|
+
): boolean {
|
|
213
|
+
try {
|
|
214
|
+
return resolveActionAsset(action?.initialEntryState?.(entry)?.asset) !== null; // prettier-ignore
|
|
215
|
+
} catch {
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
128
218
|
}
|
|
129
219
|
|
|
130
220
|
class UIActionsRegistry {
|