@blocklet/launcher-workflow 2.1.6 → 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,13 +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
118
  loading: true,
119
119
  error: '',
120
120
  plans: [],
121
+ paymentMethods: [],
122
+ paymentMethod: params.get('paymentMethod'),
121
123
  sessionId: params.get('sessionId'),
122
124
  planId: params.get('planId'),
125
+ showRedeem: false,
123
126
  showMorePrompt: false,
124
127
  arrows: false,
125
128
  perPage: 100,
@@ -129,22 +132,6 @@ function PurchasePage(_ref) {
129
132
  const api = create({
130
133
  baseURL: didPayPrefix
131
134
  });
132
- const selectCurrent = (perPage, curIndex) => {
133
- if (!state.plans.length) {
134
- return;
135
- }
136
-
137
- // 如果每页只有一个,则在翻页的时候默认选中当前项
138
- if (perPage === 1) {
139
- var _state$plans$curIndex;
140
- setState({
141
- planId: (_state$plans$curIndex = state.plans[curIndex]) === null || _state$plans$curIndex === void 0 ? void 0 : _state$plans$curIndex._id
142
- });
143
- }
144
- };
145
- (0, _react.useEffect)(() => {
146
- selectCurrent(state.perPage, 0);
147
- }, [state.perPage]);
148
135
  const selectPlan = launch => {
149
136
  if (!state.plans.length) {
150
137
  return;
@@ -166,15 +153,37 @@ function PurchasePage(_ref) {
166
153
  }
167
154
  };
168
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
+
169
172
  // 创建启动会话或者加载现有的会话
170
173
  (0, _react.useEffect)(() => {
171
- api.get('/plans').then(_ref2 => {
172
- let {
174
+ Promise.all([api.get('/plans'), api.get('/payment-methods')]).then(_ref2 => {
175
+ let [{
173
176
  data
174
- } = _ref2;
177
+ }, {
178
+ data: {
179
+ data: paymentMethods
180
+ }
181
+ }] = _ref2;
175
182
  const plans = (data || []).sort((a, b) => b.weight - a.weight);
176
183
  setState({
177
184
  plans,
185
+ paymentMethods,
186
+ paymentMethod: paymentMethods[0]._id,
178
187
  loading: false
179
188
  });
180
189
  if (isPurchaseOnly) {
@@ -250,19 +259,34 @@ function PurchasePage(_ref) {
250
259
  });
251
260
  };
252
261
  (0, _react.useEffect)(() => {
253
- if (isPurchaseOnly) {
254
- return;
255
- }
256
262
  if (!state.planId) {
257
263
  return;
258
264
  }
259
265
  if (state.planId !== params.get('planId')) {
260
266
  params.set('planId', state.planId);
261
267
  setParams(params);
262
- // FIXME: @wangshijun should not always be serverless
263
- _util.launchSession.select(api, routerPrefix, state.sessionId, 'serverless', state.planId);
264
268
  }
265
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]);
266
290
  const productFeatures = [];
267
291
  if (!state.loading && ((_state$plans3 = state.plans) === null || _state$plans3 === void 0 ? void 0 : _state$plans3.length) > 0) {
268
292
  // TODO: Pricing Table: 临时做法
@@ -284,18 +308,21 @@ function PurchasePage(_ref) {
284
308
  console.error('parse product feature failed:', error);
285
309
  }
286
310
  }
287
- const handleRedeem = async () => {
311
+ const handleRedeem = () => {
288
312
  if (session.user) {
289
313
  _util.launchSession.connect(api, routerPrefix, state.sessionId, session.user.did, () => {
290
- setShowRedeem(true);
314
+ setState({
315
+ showRedeem: true
316
+ });
291
317
  });
292
318
  } else {
293
- setShowRedeem(true);
319
+ setState({
320
+ showRedeem: true
321
+ });
294
322
  }
295
323
  };
296
324
  const handleRedeemed = _ref3 => {
297
325
  let {
298
- did,
299
326
  loginToken,
300
327
  nftId,
301
328
  type
@@ -303,25 +330,14 @@ function PurchasePage(_ref) {
303
330
  if (type === _constant.NFT_TYPE_SERVERLESS) {
304
331
  params.set('launchType', 'serverless');
305
332
  }
306
- const updateSessionAndRedirect = () => {
307
- _util.launchSession.pay(api, routerPrefix, state.sessionId, nftId, 'redeem', '', err => {
308
- if (err) {
309
- _Toast.default.error(err.message);
310
- } else {
311
- navigate({
312
- pathname: (0, _urlJoin.default)(routerPrefix, "/launch/".concat(nftId)),
313
- search: params.toString()
314
- });
315
- }
316
- });
317
- };
318
- if (session.user) {
319
- updateSessionAndRedirect();
320
- } else if (loginToken) {
321
- _util.connectStorage.setToken(decrypt(loginToken));
333
+ if (loginToken) {
334
+ storage.setToken(decrypt(loginToken));
322
335
  session.refresh();
323
- _util.launchSession.connect(api, routerPrefix, state.sessionId, did, updateSessionAndRedirect);
324
336
  }
337
+ navigate({
338
+ pathname: (0, _urlJoin.default)(routerPrefix, "/launch/".concat(nftId)),
339
+ search: params.toString()
340
+ });
325
341
  };
326
342
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(Container, {
327
343
  embed: embed,
@@ -345,7 +361,7 @@ function PurchasePage(_ref) {
345
361
  children: [embed && isPurchaseOnly === false && /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
346
362
  className: "footer-left",
347
363
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Button.default, {
348
- onClick: () => handleRedeem(),
364
+ onClick: handleRedeem,
349
365
  className: "redeem-button",
350
366
  variant: "outlined",
351
367
  children: t('purchase.redeem')
@@ -373,6 +389,11 @@ function PurchasePage(_ref) {
373
389
  children: [!isMobile && /*#__PURE__*/(0, _jsxRuntime.jsx)(_plan.default, {
374
390
  toc: true,
375
391
  productFeatures: productFeatures,
392
+ paymentMethods: state.paymentMethods,
393
+ paymentMethod: state.paymentMethod,
394
+ onChangeMethod: paymentMethod => setState({
395
+ paymentMethod
396
+ }),
376
397
  className: "toc"
377
398
  }), state.plans.length > 0 && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactSplide.Splide, {
378
399
  extensions: {
@@ -397,10 +418,6 @@ function PurchasePage(_ref) {
397
418
  }
398
419
  },
399
420
  hasTrack: false,
400
- onMoved: (splide, index) => {
401
- var _splide$options;
402
- selectCurrent((_splide$options = splide.options) === null || _splide$options === void 0 ? void 0 : _splide$options.perPage, index);
403
- },
404
421
  options: {
405
422
  pagination: true,
406
423
  arrows: state.arrows,
@@ -444,6 +461,8 @@ function PurchasePage(_ref) {
444
461
  recommend: !!plan.isRecommended,
445
462
  checked: plan._id === state.planId,
446
463
  plan: plan,
464
+ paymentMethod: state.paymentMethod,
465
+ paymentMethods: state.paymentMethods,
447
466
  onClick: () => handleSelect(plan._id)
448
467
  })
449
468
  }, plan._id))
@@ -455,17 +474,22 @@ function PurchasePage(_ref) {
455
474
  })
456
475
  })
457
476
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Connect.default, {
458
- open: showRedeem,
477
+ open: state.showRedeem,
459
478
  popup: true,
460
479
  useSocket: false,
461
480
  locale: locale,
462
- action: (_session$user = session.user) !== null && _session$user !== void 0 && _session$user.did ? 'redeem' : 'redeem-with-connect',
481
+ action: "redeem",
463
482
  prefix: "/did",
464
483
  checkFn: create().get,
465
484
  onSuccess: handleRedeemed,
466
- onClose: () => setShowRedeem(false),
485
+ onClose: () => setState({
486
+ showRedeem: false
487
+ }),
467
488
  checkTimeout: 60 * 5000,
468
489
  showDownload: false,
490
+ extraParams: {
491
+ sessionId: state.sessionId
492
+ },
469
493
  messages: {
470
494
  title: t('redeem.dialog.title'),
471
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.6",
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.6",
44
- "@blocklet/launcher-util": "2.1.6",
45
- "@blocklet/launcher-ux": "2.1.6",
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": "0ce72656e21595f9bee690ce3c3a5446d781ed50"
78
+ "gitHead": "49ba245e679952c38a172fa3babe1342c8c78eac"
79
79
  }