shopflo-appbrew 0.1.1 → 0.2.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/package.json +1 -1
- package/src/blocks/shopflo-web-view.tsx +13 -27
- package/src/utils/shopflo.ts +0 -6
package/package.json
CHANGED
|
@@ -24,7 +24,6 @@ import { useIsFocused } from '@react-navigation/native'
|
|
|
24
24
|
import {
|
|
25
25
|
isShopifyCartUrl,
|
|
26
26
|
lastSegment,
|
|
27
|
-
toCartSignature,
|
|
28
27
|
toShopfloCartUrl,
|
|
29
28
|
} from '../utils/shopflo'
|
|
30
29
|
import { toUpiAppUrl } from '../utils/payment-intents'
|
|
@@ -49,9 +48,6 @@ export function ShopfloWebview(props: ShopfloWebviewProps) {
|
|
|
49
48
|
{ checkoutUrl: string; tokenId: string; loadId: number } | undefined
|
|
50
49
|
>()
|
|
51
50
|
const isFocused = useIsFocused()
|
|
52
|
-
const cartSignature = useAppStore((s) => toCartSignature(s.cart.data.lineItems))
|
|
53
|
-
// Signature of the cart Shopflo currently shows; null until the first load
|
|
54
|
-
const loadedSignature = React.useRef<string | null>(null)
|
|
55
51
|
// Id of the newest token request; an older one resolving later is dropped
|
|
56
52
|
const latestRequest = React.useRef(0)
|
|
57
53
|
const block = useBlock(props.screenId, props.componentId, props.instanceId)
|
|
@@ -123,15 +119,12 @@ export function ShopfloWebview(props: ShopfloWebviewProps) {
|
|
|
123
119
|
}
|
|
124
120
|
|
|
125
121
|
// Get the URL from the provider
|
|
126
|
-
loadedSignature.current = toCartSignature(
|
|
127
|
-
useAppStore.getState().cart.data.lineItems
|
|
128
|
-
)
|
|
129
122
|
const request = ++latestRequest.current
|
|
130
123
|
const result =
|
|
131
124
|
page === 'checkout'
|
|
132
125
|
? await checkoutProvider.fetchCheckoutUrl()
|
|
133
126
|
: await checkoutProvider.fetchCartUrl()
|
|
134
|
-
//
|
|
127
|
+
// A newer visit started another request while this was in flight
|
|
135
128
|
if (request !== latestRequest.current) return
|
|
136
129
|
if (!result?.checkoutUrl || !result?.tokenId) {
|
|
137
130
|
console.error('Failed to get checkout URL')
|
|
@@ -160,16 +153,20 @@ export function ShopfloWebview(props: ShopfloWebviewProps) {
|
|
|
160
153
|
capturedCheckout.current = false
|
|
161
154
|
}, [page, settings, gotoLink, setOverrideBack, onUnavailable])
|
|
162
155
|
|
|
163
|
-
//
|
|
156
|
+
// Kept in a ref so only a new visit, not a re-created callback, reloads
|
|
157
|
+
const initializeRef = React.useRef(initializeWebView)
|
|
158
|
+
initializeRef.current = initializeWebView
|
|
159
|
+
|
|
160
|
+
// Every visit mints a fresh token from the app's cart; edits made inside
|
|
161
|
+
// Shopflo while it is open are only synced to the app cart, never reloaded.
|
|
164
162
|
// An empty cart (after purchase) keeps the thank-you page up
|
|
165
163
|
React.useEffect(() => {
|
|
166
|
-
if (!isFocused
|
|
167
|
-
if (
|
|
168
|
-
|
|
169
|
-
}, [isFocused
|
|
164
|
+
if (!isFocused) return
|
|
165
|
+
if (!useAppStore.getState().cart.data.lineItems.length) return
|
|
166
|
+
initializeRef.current()
|
|
167
|
+
}, [isFocused])
|
|
170
168
|
|
|
171
|
-
// Shopflo already shows edits made inside it;
|
|
172
|
-
// don't trigger a reload of the cart the user is looking at
|
|
169
|
+
// Shopflo already shows edits made inside it; only the app cart needs them
|
|
173
170
|
const syncFromShopflo = React.useCallback(
|
|
174
171
|
async (apply: () => Promise<unknown>) => {
|
|
175
172
|
try {
|
|
@@ -177,9 +174,6 @@ export function ShopfloWebview(props: ShopfloWebviewProps) {
|
|
|
177
174
|
} catch (error) {
|
|
178
175
|
console.warn('Syncing Shopflo cart change failed:', error)
|
|
179
176
|
}
|
|
180
|
-
loadedSignature.current = toCartSignature(
|
|
181
|
-
useAppStore.getState().cart.data.lineItems
|
|
182
|
-
)
|
|
183
177
|
},
|
|
184
178
|
[]
|
|
185
179
|
)
|
|
@@ -271,14 +265,6 @@ export function ShopfloWebview(props: ShopfloWebviewProps) {
|
|
|
271
265
|
// The cart view's close (X) posts CLOSE_CART_IFRAME, not FLO_EXIT_CHECKOUT
|
|
272
266
|
case 'CLOSE_CART_IFRAME':
|
|
273
267
|
case 'FLO_EXIT_CHECKOUT':
|
|
274
|
-
// On the cart screen Shopflo moved to checkout inside this WebView
|
|
275
|
-
// (is_cart_redirect); put it back on the cart so the next visit
|
|
276
|
-
// to the cart screen opens there
|
|
277
|
-
if (type === 'FLO_EXIT_CHECKOUT' && page === 'cart') {
|
|
278
|
-
setCheckoutData(
|
|
279
|
-
(prev) => prev && { ...prev, loadId: prev.loadId + 1 }
|
|
280
|
-
)
|
|
281
|
-
}
|
|
282
268
|
if (settings?.source?.closeModalId) {
|
|
283
269
|
openModal(settings.source.closeModalId)
|
|
284
270
|
} else {
|
|
@@ -292,7 +278,7 @@ export function ShopfloWebview(props: ShopfloWebviewProps) {
|
|
|
292
278
|
console.error('Error parsing message from WebView:', error)
|
|
293
279
|
}
|
|
294
280
|
},
|
|
295
|
-
[
|
|
281
|
+
[settings, back, openModal, syncFromShopflo]
|
|
296
282
|
)
|
|
297
283
|
|
|
298
284
|
if (!checkoutData) return null
|
package/src/utils/shopflo.ts
CHANGED
|
@@ -27,12 +27,6 @@ export const isShopifyCartUrl = (url: string, domain: string) =>
|
|
|
27
27
|
.replace(/^https?:\/\//, '')
|
|
28
28
|
.replace(/\/$/, '') === `${domain}/cart`
|
|
29
29
|
|
|
30
|
-
// What Shopflo was last given; a different value means the token call must
|
|
31
|
-
// run again so Shopflo's cart matches the app's
|
|
32
|
-
export const toCartSignature = (
|
|
33
|
-
lineItems: Array<{ variantId: string; quantity: number }>
|
|
34
|
-
) => lineItems.map((li) => `${li.variantId}:${li.quantity}`).join(',')
|
|
35
|
-
|
|
36
30
|
// The token's checkout_url already opens Shopflo's cart view (page=cart);
|
|
37
31
|
// is_cart_redirect=true makes its Checkout button move to checkout inside the
|
|
38
32
|
// same WebView. String-based: RN's URL lacks full searchParams
|