@blocklet/launcher-workflow 2.1.5 → 2.1.7

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/lib/checkout.js CHANGED
@@ -5,7 +5,6 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = void 0;
7
7
  var _Dialog = _interopRequireDefault(require("@arcblock/ux/lib/Dialog"));
8
- var _Toast = _interopRequireDefault(require("@arcblock/ux/lib/Toast"));
9
8
  var _util = require("@blocklet/launcher-util/lib/util");
10
9
  var _constant = require("@blocklet/launcher-util/lib/constant");
11
10
  var _button = _interopRequireDefault(require("@blocklet/launcher-ux/lib/button"));
@@ -88,8 +87,10 @@ function CheckoutPage(_ref) {
88
87
  locale
89
88
  } = (0, _locale.useLocaleContext)();
90
89
  const {
91
- session
90
+ session,
91
+ events
92
92
  } = (0, _session.useSessionContext)();
93
+ const [params] = (0, _reactRouterDom.useSearchParams)();
93
94
  const [state, setState] = (0, _useSetState.default)({
94
95
  showAgreement: false,
95
96
  showPayment: false,
@@ -100,13 +101,14 @@ function CheckoutPage(_ref) {
100
101
  },
101
102
  agreed: true,
102
103
  paying: false,
103
- paymentMethod: null
104
+ planId: params.get('planId'),
105
+ sessionId: params.get('sessionId'),
106
+ paymentMethod: params.get('paymentMethod')
104
107
  });
105
108
  const navigate = (0, _reactRouterDom.useNavigate)();
106
109
  const {
107
110
  create
108
111
  } = (0, _request.default)();
109
- const [params] = (0, _reactRouterDom.useSearchParams)();
110
112
  const {
111
113
  mobileSize,
112
114
  isMobile
@@ -118,44 +120,63 @@ function CheckoutPage(_ref) {
118
120
  isPurchaseOnly
119
121
  } = (0, _workflow.useWorkflowContext)();
120
122
  (0, _react.useEffect)(() => {
121
- if (session.user && !isPurchaseOnly) {
122
- _util2.launchSession.connect(api, routerPrefix, sessionId, session.user.did);
123
+ if (isPurchaseOnly) {
124
+ return;
125
+ }
126
+ if (session.user) {
127
+ _util2.launchSession.connect(api, routerPrefix, state.sessionId, session.user.did);
123
128
  }
124
129
  }, [session.user]);
125
130
  const api = create({
126
131
  baseURL: didPayPrefix
127
132
  });
128
133
  const enableBlockletAgreement = !!blocklet;
129
- const planId = params.get('planId');
130
- const sessionId = params.get('sessionId');
131
134
  const context = (0, _useAsync.default)(async () => {
132
135
  try {
133
136
  const [{
134
137
  data: {
135
- data: methods
138
+ data: paymentMethods
136
139
  }
137
140
  }, {
138
141
  data: {
139
142
  data: plan
140
143
  }
141
- }] = await Promise.all([api.get('/payment-methods'), api.get("/plans/".concat(planId))]);
142
- if (methods.length > 0) {
144
+ }] = await Promise.all([api.get('/payment-methods'), api.get("/plans/".concat(state.planId))]);
145
+ if (paymentMethods.length > 0 && !state.paymentMethod) {
143
146
  setState({
144
- paymentMethod: methods[0]
147
+ paymentMethod: paymentMethods[0]._id
145
148
  });
146
149
  }
147
150
  return {
148
- methods,
151
+ paymentMethods,
149
152
  plan
150
153
  };
151
154
  } catch (error) {
152
155
  console.error('load data failed:', error);
153
156
  return {
154
- methods: [],
157
+ paymentMethods: [],
155
158
  plan: null
156
159
  };
157
160
  }
158
161
  });
162
+
163
+ // 用户退出的时候自动重新创建启动会话
164
+ (0, _react.useEffect)(() => {
165
+ if (isPurchaseOnly) {
166
+ return;
167
+ }
168
+ events.on('logout', () => {
169
+ const metaUrl = params.get('blocklet_meta_url');
170
+ _util2.launchSession.create(api, routerPrefix, metaUrl, (err, launch) => {
171
+ setState({
172
+ sessionId: launch._id
173
+ });
174
+ params.set('sessionId', launch._id);
175
+ // FIXME: @wangshijun should not always be serverless
176
+ _util2.launchSession.select(api, routerPrefix, launch._id, 'serverless', state.planId);
177
+ });
178
+ });
179
+ }, []);
159
180
  const switchPayment = method => {
160
181
  setState({
161
182
  paymentMethod: method
@@ -167,7 +188,7 @@ function CheckoutPage(_ref) {
167
188
  paying: false
168
189
  });
169
190
  };
170
- const handlePay = async () => {
191
+ const handlePay = () => {
171
192
  if (enableBlockletAgreement && !state.agreed) {
172
193
  setState({
173
194
  showAgreeHint: true
@@ -189,15 +210,14 @@ function CheckoutPage(_ref) {
189
210
  session.refresh();
190
211
  return;
191
212
  }
192
- _util2.launchSession.connect(api, routerPrefix, sessionId, result.did, () => {
213
+ _util2.launchSession.connect(api, routerPrefix, state.sessionId, result.did, () => {
193
214
  session.refresh();
194
215
  });
195
216
  };
196
- const handlePaid = async _ref2 => {
217
+ const handlePaid = _ref2 => {
197
218
  let {
198
219
  nftId,
199
- nftState,
200
- paymentId
220
+ nftState
201
221
  } = _ref2;
202
222
  if ((nftState.tags || []).includes(_constant.NFT_TYPE_SERVERLESS)) {
203
223
  if (!embed) {
@@ -217,16 +237,10 @@ function CheckoutPage(_ref) {
217
237
  _dsbridge.default.call('arcClosePage');
218
238
  return;
219
239
  }
220
- _util2.launchSession.pay(api, routerPrefix, sessionId, nftId, 'purchase', paymentId, err => {
221
- handleCancelPay();
222
- if (err) {
223
- _Toast.default.error(err.message);
224
- } else {
225
- navigate({
226
- pathname: (0, _urlJoin.default)(routerPrefix, "/launch/".concat(nftId)),
227
- search: params.toString()
228
- });
229
- }
240
+ handleCancelPay();
241
+ navigate({
242
+ pathname: (0, _urlJoin.default)(routerPrefix, "/launch/".concat(nftId)),
243
+ search: params.toString()
230
244
  });
231
245
  };
232
246
  const handlePayFailed = () => {
@@ -234,18 +248,22 @@ function CheckoutPage(_ref) {
234
248
  handleCancelPay();
235
249
  };
236
250
  const calculateTotalPayment = prices => {
251
+ var _paymentMethods$find;
237
252
  if (!state.paymentMethod) {
238
253
  return '';
239
254
  }
240
- return (0, _util2.getPrice)(prices, state.paymentMethod.provider.name);
255
+ const providerName = paymentMethods === null || paymentMethods === void 0 ? void 0 : (_paymentMethods$find = paymentMethods.find(x => x._id === state.paymentMethod)) === null || _paymentMethods$find === void 0 ? void 0 : _paymentMethods$find.provider.name;
256
+ return (0, _util2.getPrice)(prices, providerName);
241
257
  };
242
258
  const toggleAgreement = () => setState({
243
259
  agreed: !state.agreed
244
260
  });
245
261
  const {
246
- methods,
262
+ paymentMethods,
247
263
  plan
248
264
  } = context.loading ? {} : context.value;
265
+ const paymentMethod = paymentMethods === null || paymentMethods === void 0 ? void 0 : paymentMethods.find(x => x._id === state.paymentMethod);
266
+ const providerName = paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.provider.name;
249
267
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(Container, {
250
268
  mobileSize: mobileSize,
251
269
  enableBlockletAgreement: enableBlockletAgreement,
@@ -278,7 +296,7 @@ function CheckoutPage(_ref) {
278
296
  })]
279
297
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
280
298
  className: "price",
281
- children: (0, _util2.getPrice)(plan.prices, 'ocap')
299
+ children: (0, _util2.getPrice)(plan.prices, providerName)
282
300
  })]
283
301
  })]
284
302
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
@@ -294,7 +312,7 @@ function CheckoutPage(_ref) {
294
312
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
295
313
  children: t('checkout.orderTotal')
296
314
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
297
- children: (0, _util2.getPrice)((plan === null || plan === void 0 ? void 0 : plan.prices) || [], 'ocap')
315
+ children: (0, _util2.getPrice)((plan === null || plan === void 0 ? void 0 : plan.prices) || [], providerName)
298
316
  })]
299
317
  }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
300
318
  className: "total-payment space",
@@ -322,7 +340,7 @@ function CheckoutPage(_ref) {
322
340
  container: true,
323
341
  spacing: 3,
324
342
  justifyContent: "flex-start",
325
- children: methods.map(method => /*#__PURE__*/(0, _jsxRuntime.jsx)(_Grid.default, {
343
+ children: paymentMethods.map(method => /*#__PURE__*/(0, _jsxRuntime.jsx)(_Grid.default, {
326
344
  item: true,
327
345
  xs: 12,
328
346
  sm: 12,
@@ -330,9 +348,9 @@ function CheckoutPage(_ref) {
330
348
  lg: 2,
331
349
  xl: 2,
332
350
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_checkbox.default, {
333
- label: method.name[locale],
334
- checked: state.paymentMethod._id === method._id,
335
- onClick: () => switchPayment(method)
351
+ label: method.currency.displayName[locale] || method.currency.displayName.en,
352
+ checked: state.paymentMethod === method._id,
353
+ onClick: () => switchPayment(method._id)
336
354
  })
337
355
  }, method._id))
338
356
  })
@@ -376,7 +394,7 @@ function CheckoutPage(_ref) {
376
394
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_button.default, {
377
395
  loading: state.paying,
378
396
  className: "button-pay",
379
- disabled: state.paying || state.showPayment || !planId || !state.paymentMethod,
397
+ disabled: state.paying || state.showPayment || !state.planId || !state.sessionId || !state.paymentMethod,
380
398
  variant: "contained",
381
399
  onClick: handlePay,
382
400
  children: t('common.pay')
@@ -384,14 +402,17 @@ function CheckoutPage(_ref) {
384
402
  })]
385
403
  }), state.showPayment && /*#__PURE__*/(0, _jsxRuntime.jsx)(_payment.default, {
386
404
  baseURL: didPayPrefix,
387
- method: state.paymentMethod,
405
+ method: paymentMethod,
388
406
  userDid: session === null || session === void 0 ? void 0 : (_session$user = session.user) === null || _session$user === void 0 ? void 0 : _session$user.did,
389
- productId: planId,
407
+ productId: state.planId,
390
408
  useSocket: false,
391
409
  onConnect: handleConnected,
392
410
  onComplete: handlePaid,
393
411
  onFailed: handlePayFailed,
394
- onCancel: handleCancelPay
412
+ onCancel: handleCancelPay,
413
+ metadata: {
414
+ sessionId: state.sessionId
415
+ }
395
416
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_confirm.default, {
396
417
  open: state.showPaidDialog.open,
397
418
  disableEscapeKeyDown: true,
@@ -81,7 +81,7 @@ function LaunchServerless(_ref) {
81
81
  })
82
82
  }), state.value && /*#__PURE__*/(0, _jsxRuntime.jsx)(_launchResultMessage.default, {
83
83
  variant: "success",
84
- title: t('prepare.serverless.allocate'),
84
+ title: t('prepare.serverless.allocated'),
85
85
  subTitle: t('prepare.serverless.prepared')
86
86
  })]
87
87
  })
@@ -9,11 +9,15 @@ var _propTypes = _interopRequireDefault(require("prop-types"));
9
9
  var _styled = _interopRequireDefault(require("@emotion/styled"));
10
10
  var _launcherUtil = require("@blocklet/launcher-util");
11
11
  var _Typography = _interopRequireDefault(require("@mui/material/Typography"));
12
+ var _MenuItem = _interopRequireDefault(require("@mui/material/MenuItem"));
13
+ var _FormControl = _interopRequireDefault(require("@mui/material/FormControl"));
14
+ var _Select = _interopRequireDefault(require("@mui/material/Select"));
12
15
  var _useMobile = _interopRequireDefault(require("@blocklet/launcher-ux/lib/use-mobile"));
16
+ var _lodash = _interopRequireDefault(require("lodash.noop"));
13
17
  var _util = require("../../lib/util");
14
18
  var _locale = require("../contexts/locale");
15
19
  var _jsxRuntime = require("react/jsx-runtime");
16
- const _excluded = ["plan", "productFeatures", "toc", "checked", "recommend"];
20
+ const _excluded = ["plan", "productFeatures", "toc", "checked", "recommend", "paymentMethods", "paymentMethod", "onChangeMethod"];
17
21
  var _templateObject, _templateObject2, _templateObject3;
18
22
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
23
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
@@ -163,12 +167,16 @@ Feature.defaultProps = {
163
167
  isMobile: false
164
168
  };
165
169
  function Plan(_ref2) {
170
+ var _paymentMethods$find;
166
171
  let {
167
172
  plan,
168
173
  productFeatures,
169
174
  toc,
170
175
  checked,
171
- recommend
176
+ recommend,
177
+ paymentMethods,
178
+ paymentMethod,
179
+ onChangeMethod
172
180
  } = _ref2,
173
181
  rest = _objectWithoutProperties(_ref2, _excluded);
174
182
  const {
@@ -182,14 +190,41 @@ function Plan(_ref2) {
182
190
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(Container, {
183
191
  className: "toc",
184
192
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
185
- className: "basic"
193
+ className: "basic-toc",
194
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Typography.default, {
195
+ className: "payment-methods",
196
+ component: "div",
197
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_FormControl.default, {
198
+ style: {
199
+ minWidth: 180
200
+ },
201
+ size: "small",
202
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Select.default, {
203
+ id: "payment-method",
204
+ value: paymentMethod,
205
+ onChange: e => onChangeMethod(e.target.value),
206
+ children: paymentMethods.map(_ref3 => {
207
+ let {
208
+ _id,
209
+ currency
210
+ } = _ref3;
211
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_MenuItem.default, {
212
+ value: _id,
213
+ children: t('common.payWith', {
214
+ currency: currency.displayName[locale] || currency.displayName.en
215
+ })
216
+ }, _id);
217
+ })
218
+ })
219
+ })
220
+ })
186
221
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
187
222
  className: "features toc__title",
188
- children: (productFeatures || []).map(_ref3 => {
223
+ children: (productFeatures || []).map(_ref4 => {
189
224
  let {
190
225
  _id,
191
226
  name
192
- } = _ref3;
227
+ } = _ref4;
193
228
  return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
194
229
  className: "feature",
195
230
  children: name[locale]
@@ -207,6 +242,7 @@ function Plan(_ref2) {
207
242
  } catch (error) {
208
243
  console.error('parse features failed:', error);
209
244
  }
245
+ const providerName = (_paymentMethods$find = paymentMethods.find(x => x._id === paymentMethod)) === null || _paymentMethods$find === void 0 ? void 0 : _paymentMethods$find.provider.name;
210
246
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(Container, _objectSpread(_objectSpread({
211
247
  checked: checked,
212
248
  className: "card-container ".concat(checked ? 'checked' : '')
@@ -229,7 +265,7 @@ function Plan(_ref2) {
229
265
  className: "price-info",
230
266
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
231
267
  className: "price",
232
- children: (0, _util.getPrice)(plan.prices, 'ocap')
268
+ children: (0, _util.getPrice)(plan.prices, providerName)
233
269
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
234
270
  className: "period",
235
271
  children: (0, _launcherUtil.prettyDuration)(plan.duration, locale)
@@ -251,17 +287,21 @@ function Plan(_ref2) {
251
287
  })]
252
288
  }));
253
289
  }
254
- const Container = _styled.default.div(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["\n display: flex;\n position: relative;\n align-items: center;\n flex-direction: column;\n border-radius: 12px;\n overflow: hidden;\n min-height: 400px;\n white-space: nowrap;\n padding: 16px;\n\n .recommend-tag {\n display: block;\n position: absolute;\n top: 4px;\n right: 32px;\n color: #fff;\n padding: 4px 100px;\n position: absolute;\n transform: translate(50%, 50%) rotate(45deg);\n white-space: nowrap;\n background-color: #fe9344;\n transform-origin: center;\n }\n\n .toc__title {\n font-weight: bolder;\n align-items: flex-start;\n }\n\n &:not(.toc) {\n width: 280px;\n color: #000;\n background-color: ", ";\n cursor: pointer;\n }\n\n &:not(.toc, .checked):hover {\n color: #000;\n background-color: #ddf6f8;\n cursor: pointer;\n }\n\n &.checked {\n color: #fff;\n background-color: ", ";\n cursor: pointer;\n }\n\n .basic {\n width: 100%;\n height: 8em;\n\n .header {\n text-align: center;\n .header__title {\n color: ", ";\n }\n\n .header__name {\n font-weight: bolder;\n }\n }\n\n .price-info {\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n height: 6.5em;\n\n .price {\n font-size: 1.5em;\n font-weight: bolder;\n }\n\n .period {\n color: ", ";\n }\n }\n }\n\n .features {\n display: flex;\n flex-direction: column;\n width: 100%;\n margin-top: auto;\n\n .feature {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 48px;\n text-align: center;\n\n // \u79FB\u52A8\u7AEF\u4E0D\u51CF\u5C0F\n @media (max-height: 960px) and (min-width: 640px) {\n height: 36px;\n font-size: 0.9rem;\n }\n\n @media (max-width: 900px) {\n justify-content: flex-start;\n }\n\n &:not(:last-child) {\n border-bottom: 1px solid;\n border-bottom-color: ", ";\n }\n }\n }\n"])), props => props.theme.palette.secondary.main, props => props.theme.palette.primary.main, props => props.checked ? '#ffffff' : '#9397a1', props => props.checked ? '#ffffff' : '#9397a1', props => props.checked || props.hovered ? 'rgba(255, 255, 255, 0.2)' : '#f6f6f6');
290
+ const Container = _styled.default.div(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["\n display: flex;\n position: relative;\n align-items: center;\n flex-direction: column;\n border-radius: 12px;\n overflow: hidden;\n min-height: 400px;\n white-space: nowrap;\n padding: 16px;\n\n .recommend-tag {\n display: block;\n position: absolute;\n top: 4px;\n right: 32px;\n color: #fff;\n padding: 4px 100px;\n position: absolute;\n transform: translate(50%, 50%) rotate(45deg);\n white-space: nowrap;\n background-color: #fe9344;\n transform-origin: center;\n }\n\n .toc__title {\n font-weight: bolder;\n align-items: flex-start;\n }\n\n &:not(.toc) {\n width: 280px;\n color: #000;\n background-color: ", ";\n cursor: pointer;\n }\n\n &:not(.toc, .checked):hover {\n color: #000;\n background-color: #ddf6f8;\n cursor: pointer;\n }\n\n &.checked {\n color: #fff;\n background-color: ", ";\n cursor: pointer;\n }\n\n .basic-toc {\n width: 100%;\n height: 8em;\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: flex-start;\n\n .payment-methods {\n padding-top: 3em;\n font-size: 1.1em;\n font-weight: bolder;\n\n select {\n margin-left: 1em;\n }\n }\n }\n\n .basic {\n width: 100%;\n height: 8em;\n\n .header {\n text-align: center;\n .header__title {\n color: ", ";\n }\n\n .header__name {\n font-weight: bolder;\n }\n }\n\n .price-info {\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n height: 6.5em;\n\n .price {\n font-size: 1.5em;\n font-weight: bolder;\n }\n\n .period {\n color: ", ";\n }\n }\n }\n\n .features {\n display: flex;\n flex-direction: column;\n width: 100%;\n margin-top: auto;\n\n .feature {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 48px;\n text-align: center;\n\n // \u79FB\u52A8\u7AEF\u4E0D\u51CF\u5C0F\n @media (max-height: 960px) and (min-width: 640px) {\n height: 36px;\n font-size: 0.9rem;\n }\n\n @media (max-width: 900px) {\n justify-content: flex-start;\n }\n\n &:not(:last-child) {\n border-bottom: 1px solid;\n border-bottom-color: ", ";\n }\n }\n }\n"])), props => props.theme.palette.secondary.main, props => props.theme.palette.primary.main, props => props.checked ? '#ffffff' : '#9397a1', props => props.checked ? '#ffffff' : '#9397a1', props => props.checked || props.hovered ? 'rgba(255, 255, 255, 0.2)' : '#f6f6f6');
255
291
  Plan.propTypes = {
256
- plan: _propTypes.default.object,
292
+ plan: _propTypes.default.object.isRequired,
293
+ paymentMethod: _propTypes.default.string.isRequired,
294
+ paymentMethods: _propTypes.default.array,
295
+ onChangeMethod: _propTypes.default.func,
257
296
  productFeatures: _propTypes.default.array,
258
297
  checked: _propTypes.default.bool,
259
298
  recommend: _propTypes.default.bool,
260
299
  toc: _propTypes.default.bool
261
300
  };
262
301
  Plan.defaultProps = {
263
- plan: null,
302
+ paymentMethods: [],
264
303
  productFeatures: [],
304
+ onChangeMethod: _lodash.default,
265
305
  checked: false,
266
306
  recommend: false,
267
307
  toc: false
@@ -38,14 +38,14 @@ function WorkflowProvider(_ref) {
38
38
  routerPrefix,
39
39
  isPurchaseOnly
40
40
  };
41
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(Provider, {
42
- value: value,
43
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_locale.LocaleProvider, {
44
- locale: locale,
45
- translations: _locales.translations,
46
- fallbackLocale: "en",
47
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_request.RequestProvider, {
48
- baseURL: baseURL,
41
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_locale.LocaleProvider, {
42
+ locale: locale,
43
+ translations: _locales.translations,
44
+ fallbackLocale: "en",
45
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_request.RequestProvider, {
46
+ baseURL: baseURL,
47
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(Provider, {
48
+ value: value,
49
49
  children: children
50
50
  })
51
51
  })
package/lib/locales/en.js CHANGED
@@ -24,6 +24,7 @@ module.exports = {
24
24
  details: 'Details',
25
25
  previous: 'Previous',
26
26
  pay: 'Pay',
27
+ payWith: 'Pay with {currency}',
27
28
  popular: 'Popular',
28
29
  space: 'Space'
29
30
  },
@@ -34,15 +35,16 @@ module.exports = {
34
35
  prepare: {
35
36
  serverless: {
36
37
  allocate: 'Waiting for space',
38
+ allocated: 'Blocklet space ready',
37
39
  preparing: 'Preparing blocklet space for you launch request...',
38
- prepared: 'The blocklet space is ready, redirecting...',
40
+ prepared: 'Blocklet space is ready for you, redirecting...',
39
41
  prepareFailed: 'Failed to prepare space! {error}'
40
42
  }
41
43
  },
42
44
  launch: {
43
45
  pageTitle: 'Prepare Space',
44
46
  invalidFftId: 'Invalid Purchase NFT ID',
45
- launchApp: 'Launch Application',
47
+ launchApp: 'Launch App',
46
48
  launching: 'Your Blocklet Space is being baked, please be patient, it usually takes about 5 minutes',
47
49
  launched: 'Your Blocklet Space is up and running',
48
50
  launchSuccess: 'Blocklet Space is successfully launched',
package/lib/locales/zh.js CHANGED
@@ -25,7 +25,8 @@ module.exports = {
25
25
  pay: '支付',
26
26
  previous: '上一步',
27
27
  popular: '推荐',
28
- space: '空间'
28
+ space: '空间',
29
+ payWith: '用{currency}支付'
29
30
  },
30
31
  license: {
31
32
  title: '空间用户协议',
package/lib/purchase.js CHANGED
@@ -7,7 +7,6 @@ exports.default = void 0;
7
7
  var _Connect = _interopRequireWildcard(require("@arcblock/did-connect/lib/Connect"));
8
8
  var _Button = _interopRequireDefault(require("@arcblock/ux/lib/Button"));
9
9
  var _Center = _interopRequireDefault(require("@arcblock/ux/lib/Center"));
10
- var _Toast = _interopRequireDefault(require("@arcblock/ux/lib/Toast"));
11
10
  var _compactLayout = _interopRequireDefault(require("@blocklet/launcher-layout/lib/compact-layout"));
12
11
  var _constant = require("@blocklet/launcher-util/lib/constant");
13
12
  var _useMobile = _interopRequireDefault(require("@blocklet/launcher-ux/lib/use-mobile"));
@@ -82,7 +81,7 @@ const getSlideConfig = (maxLength, planLength) => {
82
81
  };
83
82
  };
84
83
  function PurchasePage(_ref) {
85
- var _state$plans3, _session$user;
84
+ var _state$plans3;
86
85
  let {
87
86
  disableBack
88
87
  } = _ref;
@@ -101,7 +100,9 @@ function PurchasePage(_ref) {
101
100
  } = (0, _Connect.useSecurity)();
102
101
  const navigate = (0, _reactRouterDom.useNavigate)();
103
102
  const {
104
- session
103
+ session,
104
+ storage,
105
+ events
105
106
  } = (0, _session.useSessionContext)();
106
107
  const [params, setParams] = (0, _reactRouterDom.useSearchParams)();
107
108
  const {
@@ -113,14 +114,15 @@ function PurchasePage(_ref) {
113
114
  const [planListRef, {
114
115
  width
115
116
  }] = (0, _useMeasure.default)();
116
- const [showRedeem, setShowRedeem] = (0, _react.useState)(false);
117
117
  const [state, setState] = (0, _useSetState.default)({
118
- launch: null,
119
118
  loading: true,
120
119
  error: '',
121
120
  plans: [],
121
+ paymentMethods: [],
122
+ paymentMethod: params.get('paymentMethod'),
122
123
  sessionId: params.get('sessionId'),
123
124
  planId: params.get('planId'),
125
+ showRedeem: false,
124
126
  showMorePrompt: false,
125
127
  arrows: false,
126
128
  perPage: 100,
@@ -130,22 +132,6 @@ function PurchasePage(_ref) {
130
132
  const api = create({
131
133
  baseURL: didPayPrefix
132
134
  });
133
- const selectCurrent = (perPage, curIndex) => {
134
- if (!state.plans.length) {
135
- return;
136
- }
137
-
138
- // 如果每页只有一个,则在翻页的时候默认选中当前项
139
- if (perPage === 1) {
140
- var _state$plans$curIndex;
141
- setState({
142
- planId: (_state$plans$curIndex = state.plans[curIndex]) === null || _state$plans$curIndex === void 0 ? void 0 : _state$plans$curIndex._id
143
- });
144
- }
145
- };
146
- (0, _react.useEffect)(() => {
147
- selectCurrent(state.perPage, 0);
148
- }, [state.perPage]);
149
135
  const selectPlan = launch => {
150
136
  if (!state.plans.length) {
151
137
  return;
@@ -167,15 +153,37 @@ function PurchasePage(_ref) {
167
153
  }
168
154
  };
169
155
 
156
+ // 用户退出的时候自动重新创建启动会话
157
+ (0, _react.useEffect)(() => {
158
+ if (isPurchaseOnly) {
159
+ return;
160
+ }
161
+ events.on('logout', () => {
162
+ const metaUrl = params.get('blocklet_meta_url');
163
+ _util.launchSession.create(api, routerPrefix, metaUrl, (err, launch) => {
164
+ setState({
165
+ sessionId: launch._id
166
+ });
167
+ selectPlan(launch);
168
+ });
169
+ });
170
+ }, []);
171
+
170
172
  // 创建启动会话或者加载现有的会话
171
173
  (0, _react.useEffect)(() => {
172
- api.get('/plans').then(_ref2 => {
173
- let {
174
+ Promise.all([api.get('/plans'), api.get('/payment-methods')]).then(_ref2 => {
175
+ let [{
174
176
  data
175
- } = _ref2;
177
+ }, {
178
+ data: {
179
+ data: paymentMethods
180
+ }
181
+ }] = _ref2;
176
182
  const plans = (data || []).sort((a, b) => b.weight - a.weight);
177
183
  setState({
178
184
  plans,
185
+ paymentMethods,
186
+ paymentMethod: paymentMethods[0]._id,
179
187
  loading: false
180
188
  });
181
189
  if (isPurchaseOnly) {
@@ -185,15 +193,11 @@ function PurchasePage(_ref) {
185
193
  const metaUrl = params.get('blocklet_meta_url');
186
194
  if (params.get('sessionId')) {
187
195
  _util.launchSession.load(api, routerPrefix, params.get('sessionId'), metaUrl, (err, launch) => {
188
- setState({
189
- launch
190
- });
191
196
  selectPlan(launch);
192
197
  });
193
198
  } else if (metaUrl) {
194
199
  _util.launchSession.create(api, routerPrefix, metaUrl, (err, launch) => {
195
200
  setState({
196
- launch,
197
201
  sessionId: launch._id
198
202
  });
199
203
  selectPlan(launch);
@@ -253,16 +257,6 @@ function PurchasePage(_ref) {
253
257
  setState({
254
258
  planId
255
259
  });
256
- if (isPurchaseOnly) {
257
- return;
258
- }
259
-
260
- // FIXME: @wangshijun should not always be serverless
261
- _util.launchSession.select(api, routerPrefix, state.sessionId, 'serverless', planId, (err, launch) => {
262
- setState({
263
- launch
264
- });
265
- });
266
260
  };
267
261
  (0, _react.useEffect)(() => {
268
262
  if (!state.planId) {
@@ -273,6 +267,26 @@ function PurchasePage(_ref) {
273
267
  setParams(params);
274
268
  }
275
269
  }, [state.planId]);
270
+ (0, _react.useEffect)(() => {
271
+ if (!state.paymentMethod) {
272
+ return;
273
+ }
274
+ if (state.paymentMethod !== params.get('paymentMethod')) {
275
+ params.set('paymentMethod', state.paymentMethod);
276
+ setParams(params);
277
+ }
278
+ }, [state.paymentMethod]);
279
+ (0, _react.useEffect)(() => {
280
+ if (isPurchaseOnly) {
281
+ return;
282
+ }
283
+ if (!state.planId || !state.sessionId) {
284
+ return;
285
+ }
286
+
287
+ // FIXME: @wangshijun should not always be serverless
288
+ _util.launchSession.select(api, routerPrefix, state.sessionId, 'serverless', state.planId);
289
+ }, [state.planId, state.sessionId]);
276
290
  const productFeatures = [];
277
291
  if (!state.loading && ((_state$plans3 = state.plans) === null || _state$plans3 === void 0 ? void 0 : _state$plans3.length) > 0) {
278
292
  // TODO: Pricing Table: 临时做法
@@ -294,18 +308,21 @@ function PurchasePage(_ref) {
294
308
  console.error('parse product feature failed:', error);
295
309
  }
296
310
  }
297
- const handleRedeem = async () => {
311
+ const handleRedeem = () => {
298
312
  if (session.user) {
299
313
  _util.launchSession.connect(api, routerPrefix, state.sessionId, session.user.did, () => {
300
- setShowRedeem(true);
314
+ setState({
315
+ showRedeem: true
316
+ });
301
317
  });
302
318
  } else {
303
- setShowRedeem(true);
319
+ setState({
320
+ showRedeem: true
321
+ });
304
322
  }
305
323
  };
306
324
  const handleRedeemed = _ref3 => {
307
325
  let {
308
- did,
309
326
  loginToken,
310
327
  nftId,
311
328
  type
@@ -313,25 +330,14 @@ function PurchasePage(_ref) {
313
330
  if (type === _constant.NFT_TYPE_SERVERLESS) {
314
331
  params.set('launchType', 'serverless');
315
332
  }
316
- const updateSessionAndRedirect = () => {
317
- _util.launchSession.pay(api, routerPrefix, state.sessionId, nftId, 'redeem', '', err => {
318
- if (err) {
319
- _Toast.default.error(err.message);
320
- } else {
321
- navigate({
322
- pathname: (0, _urlJoin.default)(routerPrefix, "/launch/".concat(nftId)),
323
- search: params.toString()
324
- });
325
- }
326
- });
327
- };
328
- if (session.user) {
329
- updateSessionAndRedirect();
330
- } else if (loginToken) {
331
- _util.connectStorage.setToken(decrypt(loginToken));
333
+ if (loginToken) {
334
+ storage.setToken(decrypt(loginToken));
332
335
  session.refresh();
333
- _util.launchSession.connect(api, routerPrefix, state.sessionId, did, updateSessionAndRedirect);
334
336
  }
337
+ navigate({
338
+ pathname: (0, _urlJoin.default)(routerPrefix, "/launch/".concat(nftId)),
339
+ search: params.toString()
340
+ });
335
341
  };
336
342
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(Container, {
337
343
  embed: embed,
@@ -355,7 +361,7 @@ function PurchasePage(_ref) {
355
361
  children: [embed && isPurchaseOnly === false && /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
356
362
  className: "footer-left",
357
363
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Button.default, {
358
- onClick: () => handleRedeem(),
364
+ onClick: handleRedeem,
359
365
  className: "redeem-button",
360
366
  variant: "outlined",
361
367
  children: t('purchase.redeem')
@@ -383,6 +389,11 @@ function PurchasePage(_ref) {
383
389
  children: [!isMobile && /*#__PURE__*/(0, _jsxRuntime.jsx)(_plan.default, {
384
390
  toc: true,
385
391
  productFeatures: productFeatures,
392
+ paymentMethods: state.paymentMethods,
393
+ paymentMethod: state.paymentMethod,
394
+ onChangeMethod: paymentMethod => setState({
395
+ paymentMethod
396
+ }),
386
397
  className: "toc"
387
398
  }), state.plans.length > 0 && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactSplide.Splide, {
388
399
  extensions: {
@@ -407,10 +418,6 @@ function PurchasePage(_ref) {
407
418
  }
408
419
  },
409
420
  hasTrack: false,
410
- onMoved: (splide, index) => {
411
- var _splide$options;
412
- selectCurrent((_splide$options = splide.options) === null || _splide$options === void 0 ? void 0 : _splide$options.perPage, index);
413
- },
414
421
  options: {
415
422
  pagination: true,
416
423
  arrows: state.arrows,
@@ -454,6 +461,8 @@ function PurchasePage(_ref) {
454
461
  recommend: !!plan.isRecommended,
455
462
  checked: plan._id === state.planId,
456
463
  plan: plan,
464
+ paymentMethod: state.paymentMethod,
465
+ paymentMethods: state.paymentMethods,
457
466
  onClick: () => handleSelect(plan._id)
458
467
  })
459
468
  }, plan._id))
@@ -465,17 +474,22 @@ function PurchasePage(_ref) {
465
474
  })
466
475
  })
467
476
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Connect.default, {
468
- open: showRedeem,
477
+ open: state.showRedeem,
469
478
  popup: true,
470
479
  useSocket: false,
471
480
  locale: locale,
472
- action: (_session$user = session.user) !== null && _session$user !== void 0 && _session$user.did ? 'redeem' : 'redeem-with-connect',
481
+ action: "redeem",
473
482
  prefix: "/did",
474
483
  checkFn: create().get,
475
484
  onSuccess: handleRedeemed,
476
- onClose: () => setShowRedeem(false),
485
+ onClose: () => setState({
486
+ showRedeem: false
487
+ }),
477
488
  checkTimeout: 60 * 5000,
478
489
  showDownload: false,
490
+ extraParams: {
491
+ sessionId: state.sessionId
492
+ },
479
493
  messages: {
480
494
  title: t('redeem.dialog.title'),
481
495
  scan: t('redeem.dialog.scan'),
package/lib/util.js CHANGED
@@ -3,20 +3,14 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.getAsset = exports.getAPIResponseError = exports.connectStorage = exports.BLOCKLET_STORE_URL = void 0;
6
+ exports.getAsset = exports.getAPIResponseError = exports.BLOCKLET_STORE_URL = void 0;
7
7
  exports.getBlockletMetaUrl = getBlockletMetaUrl;
8
8
  exports.loadURL = exports.launchSession = exports.getPrice = exports.getLaunchBlockletUrl = void 0;
9
9
  var _urlJoin = _interopRequireDefault(require("url-join"));
10
10
  var _lodash = _interopRequireDefault(require("lodash.get"));
11
11
  var _lodash2 = _interopRequireDefault(require("lodash.noop"));
12
12
  var _axios = _interopRequireDefault(require("axios"));
13
- var _Storage = _interopRequireDefault(require("@arcblock/did-connect/lib/Storage"));
14
13
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
- const connectStorage = (0, _Storage.default)('login_token', 'cookie', {
16
- returnDomain: false,
17
- path: window.blocklet.groupPathPrefix || window.blocklet.pathPrefix || '/'
18
- });
19
- exports.connectStorage = connectStorage;
20
14
  const BLOCKLET_STORE_URL = (0, _lodash.default)(window, 'blocklet.LAUNCHER_BLOCKLET_STORE_URL') || 'https://store.blocklet.dev';
21
15
  exports.BLOCKLET_STORE_URL = BLOCKLET_STORE_URL;
22
16
  function getBlockletMetaUrl(registry, did) {
@@ -121,7 +115,8 @@ const getPrice = (prices, providerName) => {
121
115
  };
122
116
  exports.getPrice = getPrice;
123
117
  const launchSession = {
124
- load: (api, prefix, sessionId, url, done) => {
118
+ load: function load(api, prefix, sessionId, url) {
119
+ let done = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : _lodash2.default;
125
120
  api.get((0, _urlJoin.default)(prefix, "/launches/".concat(sessionId))).then(result => {
126
121
  done(null, result.data.launch);
127
122
  }).catch(err => {
@@ -129,7 +124,8 @@ const launchSession = {
129
124
  launchSession.create(api, prefix, url, done);
130
125
  });
131
126
  },
132
- create: (api, prefix, url, done) => {
127
+ create: function create(api, prefix, url) {
128
+ let done = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : _lodash2.default;
133
129
  api.post((0, _urlJoin.default)(prefix, '/launches'), {
134
130
  blockletMetaUrl: url,
135
131
  referrer: document.referrer
@@ -151,19 +147,8 @@ const launchSession = {
151
147
  done(err);
152
148
  });
153
149
  },
154
- pay: (api, prefix, sessionId, nftDid, nftSource, paymentId, done) => {
155
- api.post((0, _urlJoin.default)(prefix, "/launches/".concat(sessionId, "/paid")), {
156
- nftDid,
157
- nftSource,
158
- paymentId
159
- }).then(result => {
160
- done(null, result.data.launch);
161
- }).catch(err => {
162
- console.error('Failed to set launch session as paid', err);
163
- done(err);
164
- });
165
- },
166
- select: (api, prefix, sessionId, type, planId, done) => {
150
+ select: function select(api, prefix, sessionId, type, planId) {
151
+ let done = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : _lodash2.default;
167
152
  api.post((0, _urlJoin.default)(prefix, "/launches/".concat(sessionId, "/select")), {
168
153
  type,
169
154
  planId
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blocklet/launcher-workflow",
3
- "version": "2.1.5",
3
+ "version": "2.1.7",
4
4
  "description": "Purchase components for Launcher UI",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -35,15 +35,15 @@
35
35
  "react": ">=18.1.0"
36
36
  },
37
37
  "dependencies": {
38
- "@arcblock/did-connect": "^2.5.47",
39
- "@arcblock/icons": "^2.5.47",
40
- "@arcblock/license": "^2.5.47",
41
- "@arcblock/react-hooks": "^2.5.47",
42
- "@arcblock/ux": "^2.5.47",
43
- "@blocklet/launcher-layout": "2.1.5",
44
- "@blocklet/launcher-util": "2.1.5",
45
- "@blocklet/launcher-ux": "2.1.5",
46
- "@blocklet/payment": "^1.11.0",
38
+ "@arcblock/did-connect": "^2.5.48",
39
+ "@arcblock/icons": "^2.5.48",
40
+ "@arcblock/license": "^2.5.48",
41
+ "@arcblock/react-hooks": "^2.5.48",
42
+ "@arcblock/ux": "^2.5.48",
43
+ "@blocklet/launcher-layout": "2.1.7",
44
+ "@blocklet/launcher-util": "2.1.7",
45
+ "@blocklet/launcher-ux": "2.1.7",
46
+ "@blocklet/payment": "^1.12.4",
47
47
  "@emotion/react": "^11.11.0",
48
48
  "@emotion/styled": "^11.11.0",
49
49
  "@mui/icons-material": "^5.11.16",
@@ -75,5 +75,5 @@
75
75
  "babel-plugin-inline-react-svg": "^2.0.2",
76
76
  "jest": "^27.5.1"
77
77
  },
78
- "gitHead": "0ea2e85db41a58ec0398f184242c29f74f11634a"
78
+ "gitHead": "49ba245e679952c38a172fa3babe1342c8c78eac"
79
79
  }