yichong-canva2 1.1.27

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.
@@ -0,0 +1,603 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useState, useRef, useEffect } from "react";
3
+ import { handleLogin, takeSubscribeBaseline, getUserProfile } from "./login/login.js";
4
+ import { YiChongCanvaContext } from "./context.js";
5
+ import _ from "lodash";
6
+ import { getAppVersion } from "./version.js";
7
+ function reduceFreeTimes(baseUrl, passport, cnt = 1) {
8
+ const header = {
9
+ "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
10
+ "X-Access-Ticket": passport
11
+ };
12
+ const url = baseUrl + "/api/user/reduce-free-cnt?cnt=" + cnt;
13
+ return fetch(url, {
14
+ method: "POST",
15
+ headers: header,
16
+ redirect: "follow"
17
+ }).catch((error) => {
18
+ console.log("reduceFreeTimes: ", error);
19
+ reduceFreeTimes(baseUrl, passport);
20
+ });
21
+ }
22
+ function addMonthlyUsage(passport, cnt = 1, productName) {
23
+ const headers = {
24
+ "X-Access-Ticket": passport,
25
+ "Content-Type": "application/json",
26
+ "X-Access-Channel": productName
27
+ };
28
+ const data = {
29
+ cnt
30
+ };
31
+ return fetch("https://usa.imgkits.com/api/user/add-monthly-usage", {
32
+ method: "POST",
33
+ headers,
34
+ body: JSON.stringify(data)
35
+ });
36
+ }
37
+ const YiChongCanvaProvider = ({
38
+ children,
39
+ appId,
40
+ productName,
41
+ onUpdateUserStatus,
42
+ // freeTimes = 1,
43
+ baseUrl,
44
+ autoLogin = true,
45
+ testMode: _testMode = "noTest",
46
+ version = 1,
47
+ mode = "normal",
48
+ retry = 3,
49
+ maxAvailablePoints = 1
50
+ }) => {
51
+ const [userStatus, setUserStatus] = useState({});
52
+ const [credits, setCredits] = useState(0);
53
+ const [isSubscribed, setIsSubscribed] = useState(false);
54
+ const pollUserStatus = useRef(null);
55
+ const [test, setTest] = useState(_testMode);
56
+ const [isInTest, setIsInTest] = useState(false);
57
+ const [hasClickedUpgrade, setHasClickedUpgrade] = useState(false);
58
+ const stopCurrentPolling = useRef(null);
59
+ const sessionStopRef = useRef(null);
60
+ const [loginStatus, setLoginStatus] = useState("idle");
61
+ const userStatusRef = useRef({});
62
+ useEffect(() => {
63
+ userStatusRef.current = userStatus;
64
+ }, [userStatus]);
65
+ const updateUserStatus = (user) => {
66
+ if (test !== "noTest" && !user.subscription) {
67
+ user = {
68
+ ...user,
69
+ subscription: {}
70
+ };
71
+ }
72
+ if (test === "credits") {
73
+ user.subscription = {
74
+ free_cnt: 9999
75
+ };
76
+ } else if (test === "subscribed") {
77
+ user.subscription = {
78
+ detail: {
79
+ name: "yearly",
80
+ ends_at: null
81
+ }
82
+ };
83
+ } else if (test === "expired") {
84
+ user.subscription = {
85
+ detail: {
86
+ name: "yearly",
87
+ ends_at: Date.now() - 7 * 24 * 60 * 60 * 1e3
88
+ }
89
+ };
90
+ }
91
+ const new_user = _.merge({}, userStatus, user);
92
+ if (JSON.stringify(new_user) !== JSON.stringify(userStatus)) {
93
+ console.log(new_user);
94
+ setUserStatus(new_user);
95
+ }
96
+ };
97
+ const isFreeUnlimited = () => {
98
+ var _a;
99
+ return ((_a = userStatus.profile) == null ? void 0 : _a.usage_limits.free_limit) === -1;
100
+ };
101
+ const login = (tryCount = 0) => {
102
+ setLoginStatus("loading");
103
+ handleLogin({
104
+ appId,
105
+ productName
106
+ }).then((userStatus2) => {
107
+ setLoginStatus("success");
108
+ updateUserStatus(userStatus2);
109
+ onUpdateUserStatus == null ? void 0 : onUpdateUserStatus(userStatus2);
110
+ window.userId = userStatus2.userId || "";
111
+ window.pollUserSubscribe = pollUserStatus.current = (options) => {
112
+ var _a;
113
+ const {
114
+ fastIntervalMs = 5e3,
115
+ fastPhaseMs = 3e4,
116
+ slowIntervalMs = 15e3,
117
+ sessionTtlMs = 3e5
118
+ } = options || {};
119
+ setHasClickedUpgrade(true);
120
+ (_a = sessionStopRef.current) == null ? void 0 : _a.call(sessionStopRef, false);
121
+ return new Promise((resolve) => {
122
+ const userId = (window == null ? void 0 : window.userId) || "";
123
+ const baseline = takeSubscribeBaseline(userStatusRef.current);
124
+ const sessionStart = Date.now();
125
+ console.log("checkout session start", baseline);
126
+ let stopInner = null;
127
+ let settled = false;
128
+ const finish = (u) => {
129
+ if (settled) return;
130
+ settled = true;
131
+ if (stopCurrentPolling.current === exposedStop) {
132
+ stopCurrentPolling.current = null;
133
+ }
134
+ if (sessionStopRef.current === myStop) {
135
+ sessionStopRef.current = null;
136
+ }
137
+ resolve(u);
138
+ };
139
+ const finalizeWithRefresh = () => {
140
+ if (settled) return;
141
+ Promise.race([
142
+ refreshUserStatus(),
143
+ new Promise(
144
+ (r) => setTimeout(() => r(userStatusRef.current), 1e4)
145
+ )
146
+ ]).catch(() => userStatusRef.current).then((u) => finish(u || userStatusRef.current));
147
+ };
148
+ const myStop = (withRefresh) => {
149
+ stopInner == null ? void 0 : stopInner();
150
+ if (stopCurrentPolling.current === exposedStop) {
151
+ stopCurrentPolling.current = null;
152
+ }
153
+ if (sessionStopRef.current === myStop) {
154
+ sessionStopRef.current = null;
155
+ }
156
+ if (withRefresh) {
157
+ finalizeWithRefresh();
158
+ } else {
159
+ finish(userStatusRef.current);
160
+ }
161
+ };
162
+ const exposedStop = () => myStop(true);
163
+ stopCurrentPolling.current = exposedStop;
164
+ sessionStopRef.current = myStop;
165
+ getUserProfile({
166
+ productName,
167
+ userId,
168
+ isSubscribe: true,
169
+ baseline,
170
+ // 会话时长由 sessionTtlMs 主导;次数上限只作双保险
171
+ maxCount: 1e4,
172
+ maxDurationMs: sessionTtlMs,
173
+ // 快阶段过后降频
174
+ interval: () => Date.now() - sessionStart < fastPhaseMs ? fastIntervalMs : slowIntervalMs,
175
+ onStop: (fn) => {
176
+ stopInner = fn;
177
+ },
178
+ successCallback(u) {
179
+ u.userId = userId;
180
+ finish(u);
181
+ onUpdateUserStatus == null ? void 0 : onUpdateUserStatus(u);
182
+ updateUserStatus(u);
183
+ }
184
+ }).catch(() => {
185
+ console.log("checkout session ttl reached");
186
+ finalizeWithRefresh();
187
+ }).finally(() => {
188
+ if (stopCurrentPolling.current === exposedStop) {
189
+ stopCurrentPolling.current = null;
190
+ }
191
+ if (sessionStopRef.current === myStop) {
192
+ sessionStopRef.current = null;
193
+ }
194
+ });
195
+ });
196
+ };
197
+ }).catch(() => {
198
+ setLoginStatus("error");
199
+ if (tryCount < retry) {
200
+ setTimeout(() => {
201
+ login(tryCount + 1);
202
+ }, 3e3);
203
+ }
204
+ });
205
+ };
206
+ useEffect(() => {
207
+ if (!version && !productName && !baseUrl && !appId) {
208
+ throw new Error("version, productName, baseUrl, appId is required");
209
+ }
210
+ {
211
+ setTest("noTest");
212
+ }
213
+ const _version = parseInt(localStorage.getItem("version") || "");
214
+ console.log("code version: ", version);
215
+ console.log("local version: ", _version);
216
+ if (Number.isNaN(_version)) {
217
+ getAppVersion("canva_" + appId).then((res) => {
218
+ console.log("latest version: ", res.version);
219
+ if (typeof res.version !== "number") {
220
+ res.version = version + 1;
221
+ }
222
+ if (res.version >= version) {
223
+ setIsInTest(false);
224
+ localStorage.setItem("version", version.toString());
225
+ } else {
226
+ setIsInTest(true);
227
+ }
228
+ });
229
+ } else {
230
+ if (version !== _version) {
231
+ getAppVersion("canva_" + appId).then((res) => {
232
+ if (typeof res.version !== "number") {
233
+ res.version = version + 1;
234
+ }
235
+ console.log("latest version: ", res.version);
236
+ if (res.version >= version) {
237
+ setIsInTest(false);
238
+ localStorage.setItem("version", version.toString());
239
+ } else {
240
+ setIsInTest(true);
241
+ }
242
+ });
243
+ } else {
244
+ setIsInTest(false);
245
+ }
246
+ }
247
+ }, [appId, version, baseUrl, productName]);
248
+ function updateTestInfo(info) {
249
+ localStorage.setItem(
250
+ "test_info",
251
+ JSON.stringify({
252
+ ...info
253
+ })
254
+ );
255
+ }
256
+ function getTestInfo() {
257
+ const p = localStorage.getItem("test_info");
258
+ if (p) {
259
+ try {
260
+ return JSON.parse(p);
261
+ } catch {
262
+ return {
263
+ time: "",
264
+ flag: false,
265
+ usage: 0
266
+ };
267
+ }
268
+ }
269
+ return {
270
+ time: "",
271
+ flag: false,
272
+ usage: 20
273
+ };
274
+ }
275
+ function updateCredits(credits2) {
276
+ setCredits(credits2);
277
+ }
278
+ useEffect(() => {
279
+ updateUserStatus({});
280
+ }, [test]);
281
+ useEffect(() => {
282
+ if (autoLogin) {
283
+ login();
284
+ }
285
+ }, [autoLogin]);
286
+ const initCredits = () => {
287
+ var _a, _b;
288
+ if (!userStatus.subscription || !userStatus.profile) {
289
+ return;
290
+ }
291
+ const { free_cnt, is_subscribed, monthly_usage_cnt, free_usage_cnt } = userStatus.subscription;
292
+ const { usage_limits } = userStatus.profile;
293
+ const freeTimes = (usage_limits == null ? void 0 : usage_limits.free_limit) || 0;
294
+ if (isInTest) {
295
+ let isNull = false;
296
+ if (typeof free_cnt !== "number") {
297
+ isNull = true;
298
+ }
299
+ const _credits = mode === "normal" ? 20 : 1e3;
300
+ if (mode === "server_credits" && !free_cnt) {
301
+ setUserStatus((pre) => {
302
+ const _o = JSON.parse(JSON.stringify(pre));
303
+ _o.subscription.free_time = _credits;
304
+ return _o;
305
+ });
306
+ }
307
+ const freeTimeFn = () => {
308
+ if (isNull) {
309
+ return _credits;
310
+ } else {
311
+ return free_cnt || 0;
312
+ }
313
+ };
314
+ const forceUpdateUsage = localStorage.getItem("test_free_cnt") ? localStorage.getItem("test_free_cnt") !== ((_a = freeTimeFn()) == null ? void 0 : _a.toString()) : false;
315
+ localStorage.setItem("test_free_cnt", ((_b = freeTimeFn()) == null ? void 0 : _b.toString()) || "0");
316
+ const test_info = getTestInfo();
317
+ const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
318
+ if (today !== test_info.time || forceUpdateUsage) {
319
+ const usage = forceUpdateUsage ? freeTimeFn() : _credits;
320
+ updateTestInfo({
321
+ ...test_info,
322
+ time: today,
323
+ usage
324
+ });
325
+ setCredits(usage);
326
+ return;
327
+ } else {
328
+ setCredits(test_info.usage);
329
+ return;
330
+ }
331
+ }
332
+ let c = 0;
333
+ if (mode === "normal") {
334
+ if (typeof free_cnt === "number") {
335
+ if (free_cnt < 0) {
336
+ c = freeTimes + free_cnt;
337
+ } else {
338
+ c = free_cnt ?? freeTimes;
339
+ }
340
+ } else {
341
+ c = freeTimes;
342
+ }
343
+ } else {
344
+ if (typeof free_cnt === "number" && !is_subscribed) {
345
+ c = free_cnt;
346
+ } else if (is_subscribed) {
347
+ c = maxAvailablePoints - (monthly_usage_cnt || 0);
348
+ } else {
349
+ c = freeTimes - (free_usage_cnt || 0);
350
+ }
351
+ }
352
+ if (c < 0) {
353
+ c = 0;
354
+ }
355
+ setCredits(c);
356
+ };
357
+ function updateTestMode(m) {
358
+ setTest(m);
359
+ }
360
+ const initSubscribedUser = () => {
361
+ var _a, _b;
362
+ const { subscription, team_subscription } = userStatus;
363
+ let is_subscribed = false;
364
+ if (subscription && subscription.detail) {
365
+ const detail = subscription.detail;
366
+ if (detail && !detail.ends_at) is_subscribed = true;
367
+ if (detail && detail.ends_at)
368
+ is_subscribed = !!(new Date(detail.ends_at) > /* @__PURE__ */ new Date());
369
+ if (team_subscription && (team_subscription == null ? void 0 : team_subscription.detail)) is_subscribed = true;
370
+ }
371
+ const planName = checkPlanName((_b = (_a = userStatus.subscription) == null ? void 0 : _a.detail) == null ? void 0 : _b.name);
372
+ setIsSubscribed(is_subscribed);
373
+ updateUserStatus({
374
+ subscription: {
375
+ ...userStatus.subscription,
376
+ is_subscribed
377
+ },
378
+ planName
379
+ });
380
+ };
381
+ const checkPlanName = (plan_name) => {
382
+ if (!plan_name) {
383
+ return "Free";
384
+ }
385
+ if (plan_name.toLowerCase().includes("month")) {
386
+ return "Pro Monthly plan";
387
+ } else if (plan_name.toLowerCase().includes("year")) {
388
+ return "Pro Yearly plan";
389
+ } else if (plan_name.toLowerCase().includes("free")) {
390
+ return "Free";
391
+ }
392
+ return "Premium";
393
+ };
394
+ function refreshUserStatus() {
395
+ return new Promise((resolve) => {
396
+ getUserProfile({
397
+ productName,
398
+ userId: (window == null ? void 0 : window.userId) || "",
399
+ maxCount: 2,
400
+ successCallback(userStatus2) {
401
+ console.log("refreshUserStatus", userStatus2);
402
+ userStatus2.userId = (window == null ? void 0 : window.userId) || "";
403
+ onUpdateUserStatus == null ? void 0 : onUpdateUserStatus(userStatus2);
404
+ updateUserStatus(userStatus2);
405
+ resolve(userStatus2);
406
+ }
407
+ }).catch(() => {
408
+ resolve(userStatusRef.current);
409
+ });
410
+ });
411
+ }
412
+ useEffect(() => {
413
+ initCredits();
414
+ initSubscribedUser();
415
+ }, [userStatus]);
416
+ const use = (cnt = 1, force = false, notUpload = false) => {
417
+ if (test !== "noTest") return;
418
+ if (isInTest) {
419
+ let _c = credits - cnt;
420
+ if (_c < 0) {
421
+ _c = 0;
422
+ }
423
+ setCredits(_c);
424
+ const test_info = getTestInfo();
425
+ updateTestInfo({
426
+ ...test_info,
427
+ usage: _c
428
+ });
429
+ return;
430
+ }
431
+ if (isFreeUnlimited()) {
432
+ return {
433
+ canUse: true
434
+ };
435
+ }
436
+ if (isSubscribed && !force) {
437
+ handleSubscribedUse(cnt, notUpload);
438
+ } else {
439
+ handleCreditsUse(cnt, notUpload);
440
+ }
441
+ };
442
+ const handleCreditsUse = (cnt, notUpload) => {
443
+ const passport = localStorage.getItem(window.userId + "_passport") || "";
444
+ setCredits(credits - cnt);
445
+ if (!notUpload) {
446
+ reduceFreeTimes(baseUrl, passport, cnt);
447
+ }
448
+ };
449
+ const handleSubscribedUse = (cnt, notUpload) => {
450
+ var _a, _b;
451
+ const passport = localStorage.getItem(window.userId + "_passport") || "";
452
+ const { profile, subscription } = userStatus;
453
+ const { usage_limits } = profile || {};
454
+ const monthly_usage_cnt = (subscription == null ? void 0 : subscription.monthly_usage_cnt) ?? 0;
455
+ let limitUsage = ((usage_limits == null ? void 0 : usage_limits.monthly_usage_limit) ?? 0) - monthly_usage_cnt;
456
+ if (((usage_limits == null ? void 0 : usage_limits.monthly_usage_limit) ?? 0) <= -1 || limitUsage >= cnt) {
457
+ addMonthlyUsage(passport, cnt, productName);
458
+ updateUserStatus({
459
+ ...userStatus,
460
+ subscription: {
461
+ ...userStatus.subscription,
462
+ monthly_usage_cnt: (((_a = userStatus.subscription) == null ? void 0 : _a.monthly_usage_cnt) || 0) + cnt
463
+ }
464
+ });
465
+ } else if (limitUsage < cnt) {
466
+ if (limitUsage <= 0) {
467
+ limitUsage = 0;
468
+ }
469
+ if (limitUsage > 0) {
470
+ addMonthlyUsage(passport, limitUsage, productName);
471
+ updateUserStatus({
472
+ ...userStatus,
473
+ subscription: {
474
+ ...userStatus.subscription,
475
+ monthly_usage_cnt: (((_b = userStatus.subscription) == null ? void 0 : _b.monthly_usage_cnt) || 0) + limitUsage
476
+ }
477
+ });
478
+ }
479
+ handleCreditsUse(cnt - limitUsage, notUpload);
480
+ return;
481
+ }
482
+ };
483
+ const canUse = (cnt = 1, force = false) => {
484
+ if (isSubscribed && !force) {
485
+ return true;
486
+ } else {
487
+ return credits - cnt >= 0;
488
+ }
489
+ };
490
+ const canUseLimit = (cnt = 1, force = false) => {
491
+ if (isFreeUnlimited()) {
492
+ return {
493
+ canUse: true
494
+ };
495
+ }
496
+ if (isSubscribed && !force) {
497
+ const { profile, subscription } = userStatus;
498
+ const { usage_limits } = profile || {};
499
+ const monthly_usage_cnt = (subscription == null ? void 0 : subscription.monthly_usage_cnt) ?? 0;
500
+ if (!(monthly_usage_cnt >= 0) || !usage_limits) return {
501
+ error: "userStatus_error",
502
+ canUse: false
503
+ };
504
+ const totalUsage = getLimitUsage();
505
+ if (totalUsage === null) {
506
+ return {
507
+ canUse: true
508
+ };
509
+ }
510
+ const canUse2 = totalUsage - cnt >= 0;
511
+ let error = "no_credits";
512
+ if (usage_limits.monthly_usage_limit - monthly_usage_cnt - credits < 0 && credits === 0) {
513
+ error = "monthly_usage_limit";
514
+ }
515
+ return {
516
+ error: canUse2 ? void 0 : error,
517
+ canUse: canUse2
518
+ };
519
+ } else {
520
+ const canUse2 = credits - cnt >= 0;
521
+ return {
522
+ error: canUse2 ? void 0 : "no_credits",
523
+ canUse: credits - cnt >= 0
524
+ };
525
+ }
526
+ };
527
+ function getPricingLink() {
528
+ const link = `https://www.livepolls.app/${productName}/pricing?from=canva_addon&canva_id=${userStatus.userId}&close=1`;
529
+ return link;
530
+ }
531
+ const getLimitUsage = () => {
532
+ if (isSubscribed) {
533
+ const { profile, subscription } = userStatus;
534
+ const { usage_limits } = profile || {};
535
+ const monthly_usage_cnt = (subscription == null ? void 0 : subscription.monthly_usage_cnt) ?? 0;
536
+ const monthly_usage_limit = (usage_limits == null ? void 0 : usage_limits.monthly_usage_limit) ?? 0;
537
+ if (monthly_usage_limit === -1) {
538
+ return null;
539
+ }
540
+ const monthly_usage = Math.max(0, monthly_usage_limit - monthly_usage_cnt);
541
+ return Math.max(monthly_usage + credits, 0);
542
+ } else {
543
+ return credits;
544
+ }
545
+ };
546
+ const getMonthlyUsageLimit = () => {
547
+ const { profile } = userStatus;
548
+ const { usage_limits } = profile || {};
549
+ const monthly_usage_limit = (usage_limits == null ? void 0 : usage_limits.monthly_usage_limit) ?? 0;
550
+ if (monthly_usage_limit === -1) {
551
+ return null;
552
+ }
553
+ return monthly_usage_limit;
554
+ };
555
+ return /* @__PURE__ */ jsx(
556
+ YiChongCanvaContext.Provider,
557
+ {
558
+ value: {
559
+ userStatus,
560
+ updateUserStatus,
561
+ handleLogin: login,
562
+ credits,
563
+ getLimitUsage,
564
+ getMonthlyUsageLimit,
565
+ isSubscribed,
566
+ canUseLimit,
567
+ isFreeUnlimited,
568
+ canUse,
569
+ use,
570
+ // 登录前 current 为 null,返回 undefined(保持 1.1.26 行为)
571
+ pollUserStatus: (options) => {
572
+ var _a;
573
+ return (_a = pollUserStatus.current) == null ? void 0 : _a.call(pollUserStatus, options);
574
+ },
575
+ getPricingLink,
576
+ updateTestMode,
577
+ refreshUserStatus,
578
+ hasClickedUpgrade,
579
+ setHasClickedUpgrade: (v) => {
580
+ setHasClickedUpgrade(v);
581
+ },
582
+ loginStatus,
583
+ updateCredits,
584
+ stopCurrentPolling: () => {
585
+ var _a;
586
+ if (stopCurrentPolling.current) {
587
+ (_a = stopCurrentPolling.current) == null ? void 0 : _a.call(stopCurrentPolling);
588
+ return true;
589
+ }
590
+ return false;
591
+ },
592
+ manualLogin: (_retry = 1) => {
593
+ retry = _retry;
594
+ login(0);
595
+ }
596
+ },
597
+ children
598
+ }
599
+ );
600
+ };
601
+ export {
602
+ YiChongCanvaProvider
603
+ };
@@ -0,0 +1,12 @@
1
+ import { useContext } from "react";
2
+ import { YiChongCanvaContext } from "./context.js";
3
+ const useYiChongCanva = () => {
4
+ const context = useContext(YiChongCanvaContext);
5
+ if (!context) {
6
+ throw new Error("useLogin must be used within a CanvaLoginProvider");
7
+ }
8
+ return context;
9
+ };
10
+ export {
11
+ useYiChongCanva
12
+ };
@@ -0,0 +1,26 @@
1
+ function getAppVersion(key) {
2
+ const myHeaders = new Headers();
3
+ myHeaders.append("User-Agent", "Apifox/1.0.0 (https://apifox.com)");
4
+ myHeaders.append("Accept", "*/*");
5
+ myHeaders.append("Host", "usa.imgkits.com");
6
+ myHeaders.append("Connection", "keep-alive");
7
+ myHeaders.append("Content-Type", "application/x-www-form-urlencoded");
8
+ const urlencoded = new URLSearchParams();
9
+ urlencoded.append("key", key);
10
+ const requestOptions = {
11
+ method: "POST",
12
+ headers: myHeaders,
13
+ body: urlencoded,
14
+ redirect: "follow"
15
+ };
16
+ return fetch("https://usa.imgkits.com/site/get", requestOptions).then((res) => res.json()).then((res) => {
17
+ if (!(res == null ? void 0 : res.success)) {
18
+ return {};
19
+ } else {
20
+ return JSON.parse(res.data.value);
21
+ }
22
+ });
23
+ }
24
+ export {
25
+ getAppVersion
26
+ };
@@ -0,0 +1 @@
1
+ export * from './login';