dsh-workbuddy-xdpool 1.0.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +102 -0
- package/lib/bin.js +2208 -12
- package/lib/client.js +553 -64
- package/lib/index.d.ts +1217 -5
- package/lib/index.js +2651 -151
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -28,6 +28,10 @@ window.__ModuleLoader__.load({
|
|
|
28
28
|
const POOL_RESET_COOLDOWN_PATH = "/plugins/dsh-workbuddy-xdpool/cooldowns/reset";
|
|
29
29
|
/** Plugin-owned daily check-in action endpoint (claim today's reward). */
|
|
30
30
|
const POOL_CHECKIN_PATH = "/plugins/dsh-workbuddy-xdpool/checkin";
|
|
31
|
+
/** Run one automation job immediately, so the card can verify it on demand. */
|
|
32
|
+
const POOL_AUTOMATION_RUN_PATH = "/plugins/dsh-workbuddy-xdpool/automation/run";
|
|
33
|
+
/** Set or clear one account's reserved-credit floor. */
|
|
34
|
+
const POOL_CREDIT_RESERVE_PATH = "/plugins/dsh-workbuddy-xdpool/accounts/credit-reserve";
|
|
31
35
|
//#endregion
|
|
32
36
|
//#region src/client/icon.ts
|
|
33
37
|
/**
|
|
@@ -116,13 +120,16 @@ window.__ModuleLoader__.load({
|
|
|
116
120
|
.dsm-workbuddy-xdpool-usage-dot{width:9px;height:9px;border-radius:50%;flex:0 0 auto}
|
|
117
121
|
.dsm-workbuddy-xdpool-usage-hint{padding-left:19px;color:var(--dsw-alias-label-tertiary,#9aa0a8);font-size:12px;line-height:18px}
|
|
118
122
|
/* Distribution switch: priority (drain one) vs round-robin (spread). */
|
|
119
|
-
.dsm-workbuddy-xdpool-dist{display:flex;
|
|
123
|
+
.dsm-workbuddy-xdpool-dist{display:flex;flex-direction:column;gap:6px;padding-left:19px;margin-top:8px}
|
|
120
124
|
.dsm-workbuddy-xdpool-dist-title{color:var(--dsw-alias-label-tertiary,#9aa0a8);font-size:12px;line-height:18px}
|
|
121
|
-
.dsm-workbuddy-xdpool-dist-option{appearance:none;font:inherit;cursor:pointer;border:1px solid var(--dsw-alias-border-l2,#3a3d45);border-radius:
|
|
125
|
+
.dsm-workbuddy-xdpool-dist-option{appearance:none;font:inherit;cursor:pointer;text-align:left;display:flex;flex-direction:column;justify-content:center;gap:2px;min-height:44px;border:1px solid var(--dsw-alias-border-l2,#3a3d45);border-radius:8px;padding:6px 10px;background:transparent;color:var(--dsw-alias-label-tertiary,#9aa0a8);transition:color .16s,border-color .16s,background .16s}
|
|
122
126
|
.dsm-workbuddy-xdpool-dist-option:hover:not(:disabled):not(.dsm-workbuddy-xdpool-dist-option-active){color:var(--dsw-alias-label-primary,#e6e6e6);border-color:var(--dsw-alias-label-dimmed,#777)}
|
|
123
127
|
.dsm-workbuddy-xdpool-dist-option:focus-visible{outline:2px solid var(--dsw-alias-brand-primary,#5686fe);outline-offset:1px}
|
|
124
128
|
.dsm-workbuddy-xdpool-dist-option-active{background:var(--dsw-alias-state-success-subtle,rgba(34,160,107,.14));border-color:var(--dsw-alias-state-success-primary,#22a06b);color:var(--dsw-alias-state-success-primary,#22a06b)}
|
|
125
129
|
.dsm-workbuddy-xdpool-dist-option:disabled{cursor:default;opacity:.6}
|
|
130
|
+
.dsm-workbuddy-xdpool-dist-option-name{font-size:11px;line-height:16px;font-weight:600}
|
|
131
|
+
.dsm-workbuddy-xdpool-dist-option-hint{font-size:10px;line-height:14px;opacity:.8}
|
|
132
|
+
.dsm-workbuddy-xdpool-dist-options{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}
|
|
126
133
|
.dsm-workbuddy-xdpool-usage-actions{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
|
|
127
134
|
|
|
128
135
|
/* Account list (each account = a labeled subpanel, same as dingminhua). */
|
|
@@ -243,6 +250,40 @@ window.__ModuleLoader__.load({
|
|
|
243
250
|
.dsm-workbuddy-xdpool-checkin-meta{align-items:flex-start}
|
|
244
251
|
.dsm-workbuddy-xdpool-checkin-bonus{text-align:left}
|
|
245
252
|
}
|
|
253
|
+
|
|
254
|
+
/* Automation panel: schedule and last-run summary, collapsed behind a switch. */
|
|
255
|
+
.dsm-workbuddy-xdpool-auto{margin-top:12px;padding:10px 12px;border:1px solid var(--dsw-alias-border-l2,#36373b);border-radius:10px;background:var(--dsw-alias-bg-module-platform,#202126)}
|
|
256
|
+
.dsm-workbuddy-xdpool-auto-head{display:flex;align-items:center;justify-content:space-between;gap:8px}
|
|
257
|
+
.dsm-workbuddy-xdpool-auto-title{color:var(--dsw-alias-label-primary,#e8e8ea);font-size:12px;font-weight:600}
|
|
258
|
+
.dsm-workbuddy-xdpool-auto-switch{padding:3px 12px;border:1px solid var(--dsw-alias-border-l2,#36373b);border-radius:999px;background:transparent;color:var(--dsw-alias-label-dimmed,#8a97b5);font-size:11px;cursor:pointer;transition:color .16s,border-color .16s,background .16s}
|
|
259
|
+
.dsm-workbuddy-xdpool-auto-switch:hover:not(:disabled){border-color:var(--dsw-alias-label-dimmed,#777);color:var(--dsw-alias-label-primary,#e8e8ea)}
|
|
260
|
+
.dsm-workbuddy-xdpool-auto-switch:disabled{opacity:.5;cursor:not-allowed}
|
|
261
|
+
.dsm-workbuddy-xdpool-auto-switch-on{border-color:#28c8b4;color:#28c8b4;background:rgba(40,200,180,.12)}
|
|
262
|
+
.dsm-workbuddy-xdpool-auto-hint{margin:6px 0 0;color:var(--dsw-alias-label-dimmed,#8a97b5);font-size:11px;line-height:1.5}
|
|
263
|
+
.dsm-workbuddy-xdpool-auto-total{display:flex;align-items:baseline;justify-content:space-between;gap:8px;margin-top:8px;padding:6px 8px;border-radius:8px;background:rgba(40,200,180,.08);font-size:11px}
|
|
264
|
+
.dsm-workbuddy-xdpool-auto-total-label{color:var(--dsw-alias-label-dimmed,#8a97b5)}
|
|
265
|
+
.dsm-workbuddy-xdpool-auto-total{display:flex;flex-direction:column;gap:4px;margin-top:8px;padding:6px 8px;border-radius:8px;background:rgba(40,200,180,.08);font-size:11px}
|
|
266
|
+
.dsm-workbuddy-xdpool-auto-total-list{display:flex;flex-direction:column;gap:2px}
|
|
267
|
+
.dsm-workbuddy-xdpool-auto-total-row{color:#28c8b4;font-variant-numeric:tabular-nums}
|
|
268
|
+
.dsm-workbuddy-xdpool-earned{display:flex;flex-direction:column;gap:4px;margin-top:8px;padding-top:8px;border-top:1px dashed var(--dsw-alias-border-l2,#36373b);font-size:11px}
|
|
269
|
+
.dsm-workbuddy-xdpool-earned-label{color:var(--dsw-alias-label-dimmed,#8a97b5)}
|
|
270
|
+
.dsm-workbuddy-xdpool-earned-list{display:flex;flex-direction:column;gap:2px}
|
|
271
|
+
.dsm-workbuddy-xdpool-earned-row{color:#28c8b4;font-variant-numeric:tabular-nums}
|
|
272
|
+
.dsm-workbuddy-xdpool-earned-value{color:#28c8b4;font-weight:600;font-variant-numeric:tabular-nums}
|
|
273
|
+
.dsm-workbuddy-xdpool-auto-jobs{margin-top:8px;display:flex;flex-direction:column;gap:4px}
|
|
274
|
+
.dsm-workbuddy-xdpool-auto-job{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:11px;color:var(--dsw-alias-label-dimmed,#8a97b5)}
|
|
275
|
+
.dsm-workbuddy-xdpool-auto-job-name{flex:0 0 72px;color:var(--dsw-alias-label-primary,#e8e8ea)}
|
|
276
|
+
.dsm-workbuddy-xdpool-auto-job-when{flex:1 1 auto;font-variant-numeric:tabular-nums}
|
|
277
|
+
.dsm-workbuddy-xdpool-auto-job-last{flex:0 0 auto;text-align:right;font-variant-numeric:tabular-nums}
|
|
278
|
+
.dsm-workbuddy-xdpool-auto-run{flex:0 0 auto;padding:2px 8px;font-size:10px;line-height:16px}
|
|
279
|
+
/* Reserved credits: one inline number field per account. */
|
|
280
|
+
.dsm-workbuddy-xdpool-reserve{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-top:8px;padding-top:8px;border-top:1px dashed var(--dsw-alias-border-l2,#36373b);font-size:11px;color:var(--dsw-alias-label-dimmed,#8a97b5)}
|
|
281
|
+
.dsm-workbuddy-xdpool-reserve-label{flex:0 0 auto}
|
|
282
|
+
.dsm-workbuddy-xdpool-reserve-input{width:76px;padding:2px 6px;border:1px solid var(--dsw-alias-border-l2,#36373b);border-radius:6px;background:transparent;color:var(--dsw-alias-label-primary,#e8e8ea);font:inherit;font-variant-numeric:tabular-nums}
|
|
283
|
+
.dsm-workbuddy-xdpool-reserve-input:focus-visible{outline:2px solid var(--dsw-alias-brand-primary,#5686fe);outline-offset:1px}
|
|
284
|
+
.dsm-workbuddy-xdpool-reserve-input:disabled{opacity:.6}
|
|
285
|
+
.dsm-workbuddy-xdpool-reserve-unit{flex:0 0 auto}
|
|
286
|
+
.dsm-workbuddy-xdpool-reserve-badge{flex:0 0 auto;padding:1px 7px;border-radius:999px;background:rgba(232,90,90,.14);color:#e85a5a;font-size:10px}
|
|
246
287
|
`.trim();
|
|
247
288
|
//#endregion
|
|
248
289
|
//#region src/client/PoolCard.tsx
|
|
@@ -303,6 +344,44 @@ window.__ModuleLoader__.load({
|
|
|
303
344
|
minute: "2-digit"
|
|
304
345
|
}).format(new Date(ms));
|
|
305
346
|
}
|
|
347
|
+
/**
|
|
348
|
+
* The automation jobs, in the order they run.
|
|
349
|
+
*
|
|
350
|
+
* The order is the contract: the report has to land before the task pass, or
|
|
351
|
+
* the task pass reads progress the report would have lit. `hoursOf` reads the
|
|
352
|
+
* matching hour list off the status document so the panel stays in step with
|
|
353
|
+
* whatever schedule the scheduler is actually running on.
|
|
354
|
+
*/
|
|
355
|
+
/**
|
|
356
|
+
* How long to watch a manual run before giving up on it.
|
|
357
|
+
*
|
|
358
|
+
* A pass runs one upstream call per account per job, so ~30s for a handful of
|
|
359
|
+
* accounts. The bound exists so a wedged run cannot spin the button forever;
|
|
360
|
+
* the run itself keeps going in the background either way.
|
|
361
|
+
*/
|
|
362
|
+
const AUTOMATION_POLL_MS = 2e3;
|
|
363
|
+
const AUTOMATION_POLL_ATTEMPTS = 90;
|
|
364
|
+
const AUTOMATION_JOBS = [
|
|
365
|
+
"report",
|
|
366
|
+
"tasks",
|
|
367
|
+
"checkin",
|
|
368
|
+
"streak"
|
|
369
|
+
];
|
|
370
|
+
/** Read one job's configured hours off the status document. */
|
|
371
|
+
function automationHours(status, kind) {
|
|
372
|
+
const automation = status.automation;
|
|
373
|
+
if (automation === void 0) return [];
|
|
374
|
+
switch (kind) {
|
|
375
|
+
case "report": return automation.reportHours;
|
|
376
|
+
case "tasks": return automation.taskHours;
|
|
377
|
+
case "checkin": return automation.checkinHours;
|
|
378
|
+
case "streak": return automation.streakHours;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
/** Read one job's last-run record off the status document. */
|
|
382
|
+
function automationJob(status, kind) {
|
|
383
|
+
return status.automation?.jobs[kind];
|
|
384
|
+
}
|
|
306
385
|
function dotColor(status) {
|
|
307
386
|
return status === "ok" ? "var(--dsw-alias-state-success-primary, #22a06b)" : status === "error" ? "var(--dsw-alias-state-error-primary, #ef4444)" : "var(--dsw-alias-label-dimmed, #9aa0a6)";
|
|
308
387
|
}
|
|
@@ -389,9 +468,35 @@ window.__ModuleLoader__.load({
|
|
|
389
468
|
const [statusByRegion, setStatusByRegion] = (0, react.useState)({});
|
|
390
469
|
/** The document for the tab on screen; undefined until its first answer. */
|
|
391
470
|
const status = statusByRegion[activeRegion];
|
|
471
|
+
/**
|
|
472
|
+
* Today's automation take, summed across accounts.
|
|
473
|
+
*
|
|
474
|
+
* Summed from the per-account counters rather than kept separately, so the
|
|
475
|
+
* panel total and the per-account lines can never disagree.
|
|
476
|
+
*/
|
|
477
|
+
const automationTotals = Object.values(status?.automation?.earningsToday ?? {}).reduce((sum, entry) => ({
|
|
478
|
+
credit: sum.credit + entry.credit,
|
|
479
|
+
energy: sum.energy + entry.energy,
|
|
480
|
+
claimed: sum.claimed + entry.claimed,
|
|
481
|
+
checkinCredit: sum.checkinCredit + entry.checkinCredit,
|
|
482
|
+
bonusCredit: sum.bonusCredit + entry.bonusCredit,
|
|
483
|
+
travelCredit: sum.travelCredit + entry.travelCredit
|
|
484
|
+
}), {
|
|
485
|
+
credit: 0,
|
|
486
|
+
energy: 0,
|
|
487
|
+
claimed: 0,
|
|
488
|
+
checkinCredit: 0,
|
|
489
|
+
bonusCredit: 0,
|
|
490
|
+
travelCredit: 0
|
|
491
|
+
});
|
|
392
492
|
const [error, setError] = (0, react.useState)(void 0);
|
|
393
493
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
394
494
|
const [cooldownBusy, setCooldownBusy] = (0, react.useState)(false);
|
|
495
|
+
const [automationBusy, setAutomationBusy] = (0, react.useState)(false);
|
|
496
|
+
/** The automation job currently running from the card, if any. */
|
|
497
|
+
const [automationRun, setAutomationRun] = (0, react.useState)(void 0);
|
|
498
|
+
/** Account id whose reserved-credit floor is being saved, if any. */
|
|
499
|
+
const [reserveBusy, setReserveBusy] = (0, react.useState)(void 0);
|
|
395
500
|
const [flash, setFlash] = (0, react.useState)(void 0);
|
|
396
501
|
/** Account id whose daily claim is currently in flight. */
|
|
397
502
|
const [checkinBusyId, setCheckinBusyId] = (0, react.useState)(void 0);
|
|
@@ -445,8 +550,10 @@ window.__ModuleLoader__.load({
|
|
|
445
550
|
}));
|
|
446
551
|
setError(void 0);
|
|
447
552
|
}
|
|
553
|
+
return value;
|
|
448
554
|
} catch (cause) {
|
|
449
555
|
if (mounted.current && signal?.aborted !== true) setError(cause instanceof Error ? cause.message : String(cause));
|
|
556
|
+
return;
|
|
450
557
|
}
|
|
451
558
|
}, []);
|
|
452
559
|
(0, react.useEffect)(() => {
|
|
@@ -646,6 +753,116 @@ window.__ModuleLoader__.load({
|
|
|
646
753
|
if (mounted.current) setError(String(cause));
|
|
647
754
|
}
|
|
648
755
|
};
|
|
756
|
+
/**
|
|
757
|
+
* Switch the daily-points automation on or off.
|
|
758
|
+
*
|
|
759
|
+
* The whole `automation` object is written as one key, because that is how the
|
|
760
|
+
* settings document stores it: the schedule fields must be carried along, or a
|
|
761
|
+
* save would drop the hour lists the scheduler is running on.
|
|
762
|
+
*/
|
|
763
|
+
const setAutomationEnabled = async (enabled) => {
|
|
764
|
+
const write = settingsScope?.set;
|
|
765
|
+
if (write === void 0) {
|
|
766
|
+
setError(t?.("row.modelsSaveError", { message: "settings scope is read-only" }) ?? "settings scope is read-only");
|
|
767
|
+
return;
|
|
768
|
+
}
|
|
769
|
+
const existing = status?.automation;
|
|
770
|
+
setAutomationBusy(true);
|
|
771
|
+
setFlash(void 0);
|
|
772
|
+
try {
|
|
773
|
+
await write.call(settingsScope, "automation", {
|
|
774
|
+
...existing === void 0 ? {} : {
|
|
775
|
+
checkinHours: [...existing.checkinHours],
|
|
776
|
+
reportHours: [...existing.reportHours],
|
|
777
|
+
taskHours: [...existing.taskHours],
|
|
778
|
+
streakHours: [...existing.streakHours]
|
|
779
|
+
},
|
|
780
|
+
enabled
|
|
781
|
+
});
|
|
782
|
+
await refresh(activeRegion);
|
|
783
|
+
} catch (cause) {
|
|
784
|
+
if (mounted.current) setError(String(cause));
|
|
785
|
+
} finally {
|
|
786
|
+
if (mounted.current) setAutomationBusy(false);
|
|
787
|
+
}
|
|
788
|
+
};
|
|
789
|
+
/**
|
|
790
|
+
/**
|
|
791
|
+
* Run the whole automation pass now.
|
|
792
|
+
*
|
|
793
|
+
* The route only STARTS the pass: a full run takes tens of seconds, which is
|
|
794
|
+
* far too long to hold a request open. This watches the scheduler status until
|
|
795
|
+
* the run settles, so the panel can show "running" honestly and report the
|
|
796
|
+
* result when it lands.
|
|
797
|
+
*/
|
|
798
|
+
const runAutomationJob = async () => {
|
|
799
|
+
setAutomationRun("all");
|
|
800
|
+
setFlash(void 0);
|
|
801
|
+
try {
|
|
802
|
+
const response = await fetch(POOL_AUTOMATION_RUN_PATH, {
|
|
803
|
+
method: "POST",
|
|
804
|
+
headers: {
|
|
805
|
+
"accept": "application/json",
|
|
806
|
+
"content-type": "application/json"
|
|
807
|
+
},
|
|
808
|
+
credentials: "same-origin",
|
|
809
|
+
body: JSON.stringify({ job: "all" })
|
|
810
|
+
});
|
|
811
|
+
const body = await response.json();
|
|
812
|
+
if (!response.ok) throw new Error(body.error ?? `HTTP ${response.status}`);
|
|
813
|
+
if (body.started === false) {
|
|
814
|
+
if (mounted.current) setFlash(t?.("row.autoAlreadyRunning") ?? "A run is already in progress");
|
|
815
|
+
}
|
|
816
|
+
let settled = false;
|
|
817
|
+
for (let attempt = 0; attempt < AUTOMATION_POLL_ATTEMPTS; attempt += 1) {
|
|
818
|
+
await new Promise((resolve) => setTimeout(resolve, AUTOMATION_POLL_MS));
|
|
819
|
+
if (!mounted.current) return;
|
|
820
|
+
if ((await refresh(activeRegion))?.automation?.runInProgress === false) {
|
|
821
|
+
settled = true;
|
|
822
|
+
break;
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
await refresh(activeRegion);
|
|
826
|
+
if (mounted.current) setFlash(settled ? t?.("row.autoRunDone") ?? "Automation pass finished" : t?.("row.autoRunTimeout") ?? "Still running; check back in a moment");
|
|
827
|
+
} catch (cause) {
|
|
828
|
+
if (mounted.current) setError(cause instanceof Error ? cause.message : String(cause));
|
|
829
|
+
} finally {
|
|
830
|
+
if (mounted.current) setAutomationRun(void 0);
|
|
831
|
+
}
|
|
832
|
+
};
|
|
833
|
+
/**
|
|
834
|
+
* Save one account reserved-credit floor.
|
|
835
|
+
*
|
|
836
|
+
* A reserve only protects credits if the pool knows the balance, so this
|
|
837
|
+
* also refreshes the account list afterwards: the reserve badge appears
|
|
838
|
+
* as soon as the reading crosses the floor.
|
|
839
|
+
*/
|
|
840
|
+
const saveCreditReserve = async (accountId, reserve) => {
|
|
841
|
+
setReserveBusy(accountId);
|
|
842
|
+
setFlash(void 0);
|
|
843
|
+
try {
|
|
844
|
+
const response = await fetch(POOL_CREDIT_RESERVE_PATH, {
|
|
845
|
+
method: "POST",
|
|
846
|
+
headers: {
|
|
847
|
+
"accept": "application/json",
|
|
848
|
+
"content-type": "application/json"
|
|
849
|
+
},
|
|
850
|
+
credentials: "same-origin",
|
|
851
|
+
body: JSON.stringify({
|
|
852
|
+
accountId,
|
|
853
|
+
reserve
|
|
854
|
+
})
|
|
855
|
+
});
|
|
856
|
+
const body = await response.json();
|
|
857
|
+
if (!response.ok) throw new Error(body.error ?? `HTTP ${response.status}`);
|
|
858
|
+
await refresh(activeRegion);
|
|
859
|
+
if (mounted.current) setFlash(reserve > 0 ? t?.("row.reserveSaved", { credits: reserve }) ?? `Keeping ${reserve} credits` : t?.("row.reserveCleared") ?? "Reserve cleared");
|
|
860
|
+
} catch (cause) {
|
|
861
|
+
if (mounted.current) setError(cause instanceof Error ? cause.message : String(cause));
|
|
862
|
+
} finally {
|
|
863
|
+
if (mounted.current) setReserveBusy(void 0);
|
|
864
|
+
}
|
|
865
|
+
};
|
|
649
866
|
const saveModels = async () => {
|
|
650
867
|
if (draft === void 0 || status === void 0) return;
|
|
651
868
|
if (enabledCount === 0) {
|
|
@@ -774,26 +991,35 @@ window.__ModuleLoader__.load({
|
|
|
774
991
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
775
992
|
className: "dsm-workbuddy-xdpool-dist-title",
|
|
776
993
|
children: t?.("row.distTitle") ?? "Account usage"
|
|
777
|
-
}),
|
|
778
|
-
"
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
994
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
995
|
+
className: "dsm-workbuddy-xdpool-dist-options",
|
|
996
|
+
children: [
|
|
997
|
+
"priority",
|
|
998
|
+
"balanced",
|
|
999
|
+
"round-robin"
|
|
1000
|
+
].map((option) => {
|
|
1001
|
+
const active = (status.distribution ?? "priority") === option;
|
|
1002
|
+
const label = option === "priority" ? t?.("row.distPriority") ?? "Priority" : option === "balanced" ? t?.("row.distBalanced") ?? "Balanced" : t?.("row.distRoundRobin") ?? "Round-robin";
|
|
1003
|
+
const hint = option === "priority" ? t?.("row.distPriorityHint") ?? "" : option === "balanced" ? t?.("row.distBalancedHint") ?? "" : t?.("row.distRoundRobinHint") ?? "";
|
|
1004
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
1005
|
+
type: "button",
|
|
1006
|
+
role: "radio",
|
|
1007
|
+
"aria-checked": active,
|
|
1008
|
+
title: hint,
|
|
1009
|
+
disabled: !modelsEditable,
|
|
1010
|
+
className: "dsm-workbuddy-xdpool-dist-option" + (active ? " dsm-workbuddy-xdpool-dist-option-active" : ""),
|
|
1011
|
+
onClick: () => {
|
|
1012
|
+
setDistribution(option);
|
|
1013
|
+
},
|
|
1014
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1015
|
+
className: "dsm-workbuddy-xdpool-dist-option-name",
|
|
1016
|
+
children: label
|
|
1017
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1018
|
+
className: "dsm-workbuddy-xdpool-dist-option-hint",
|
|
1019
|
+
children: hint
|
|
1020
|
+
})]
|
|
1021
|
+
}, option);
|
|
1022
|
+
})
|
|
797
1023
|
})]
|
|
798
1024
|
})
|
|
799
1025
|
]
|
|
@@ -818,6 +1044,101 @@ window.__ModuleLoader__.load({
|
|
|
818
1044
|
}) : null]
|
|
819
1045
|
})]
|
|
820
1046
|
}),
|
|
1047
|
+
activeRegion !== "cn" || status?.automation === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
1048
|
+
className: "dsm-workbuddy-xdpool-auto",
|
|
1049
|
+
"aria-label": t?.("row.autoTitle") ?? "Automation",
|
|
1050
|
+
children: [
|
|
1051
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1052
|
+
className: "dsm-workbuddy-xdpool-auto-head",
|
|
1053
|
+
children: [
|
|
1054
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1055
|
+
className: "dsm-workbuddy-xdpool-auto-title",
|
|
1056
|
+
children: t?.("row.autoTitle") ?? "Automation"
|
|
1057
|
+
}),
|
|
1058
|
+
!status.automation.enabled ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1059
|
+
type: "button",
|
|
1060
|
+
className: "dsm-btn dsm-btn-outline dsm-workbuddy-xdpool-auto-run",
|
|
1061
|
+
disabled: automationRun !== void 0,
|
|
1062
|
+
onClick: () => {
|
|
1063
|
+
runAutomationJob();
|
|
1064
|
+
},
|
|
1065
|
+
children: automationRun !== void 0 ? t?.("row.autoRunning") ?? "Running…" : t?.("row.autoRunAll") ?? "Run all now"
|
|
1066
|
+
}),
|
|
1067
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1068
|
+
type: "button",
|
|
1069
|
+
role: "switch",
|
|
1070
|
+
"aria-checked": status.automation.enabled,
|
|
1071
|
+
disabled: !settingsWritable || automationBusy,
|
|
1072
|
+
className: `dsm-workbuddy-xdpool-auto-switch${status.automation.enabled ? " dsm-workbuddy-xdpool-auto-switch-on" : ""}`,
|
|
1073
|
+
onClick: () => {
|
|
1074
|
+
setAutomationEnabled(!status.automation.enabled);
|
|
1075
|
+
},
|
|
1076
|
+
children: automationBusy ? t?.("row.autoBusy") ?? "Saving…" : status.automation.enabled ? t?.("row.autoOn") ?? "On" : t?.("row.autoOff") ?? "Off"
|
|
1077
|
+
})
|
|
1078
|
+
]
|
|
1079
|
+
}),
|
|
1080
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1081
|
+
className: "dsm-workbuddy-xdpool-auto-hint",
|
|
1082
|
+
children: status.automation.enabled ? t?.("row.autoHintOn") ?? "Reports activity, claims task rewards and checks in once a day." : t?.("row.autoHintOff") ?? "Off: no background requests are made for you."
|
|
1083
|
+
}),
|
|
1084
|
+
automationTotals.credit === 0 && automationTotals.checkinCredit === 0 && automationTotals.bonusCredit === 0 && automationTotals.travelCredit === 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1085
|
+
className: "dsm-workbuddy-xdpool-auto-total",
|
|
1086
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1087
|
+
className: "dsm-workbuddy-xdpool-auto-total-label",
|
|
1088
|
+
children: t?.("row.autoToday") ?? "Today"
|
|
1089
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1090
|
+
className: "dsm-workbuddy-xdpool-auto-total-list",
|
|
1091
|
+
children: [
|
|
1092
|
+
automationTotals.credit > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1093
|
+
className: "dsm-workbuddy-xdpool-auto-total-row",
|
|
1094
|
+
children: t?.("row.autoFromTasks", {
|
|
1095
|
+
credit: automationTotals.credit,
|
|
1096
|
+
energy: automationTotals.energy,
|
|
1097
|
+
count: automationTotals.claimed
|
|
1098
|
+
}) ?? `Tasks +${automationTotals.credit}`
|
|
1099
|
+
}) : null,
|
|
1100
|
+
automationTotals.checkinCredit > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1101
|
+
className: "dsm-workbuddy-xdpool-auto-total-row",
|
|
1102
|
+
children: t?.("row.autoFromCheckin", { credit: automationTotals.checkinCredit }) ?? `Check-in +${automationTotals.checkinCredit}`
|
|
1103
|
+
}) : null,
|
|
1104
|
+
automationTotals.bonusCredit > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1105
|
+
className: "dsm-workbuddy-xdpool-auto-total-row",
|
|
1106
|
+
children: t?.("row.autoFromBonus", { credit: automationTotals.bonusCredit }) ?? `Streak +${automationTotals.bonusCredit}`
|
|
1107
|
+
}) : null,
|
|
1108
|
+
automationTotals.travelCredit > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1109
|
+
className: "dsm-workbuddy-xdpool-auto-total-row",
|
|
1110
|
+
children: t?.("row.autoFromTravel", { credit: automationTotals.travelCredit }) ?? `Buddy +${automationTotals.travelCredit}`
|
|
1111
|
+
}) : null
|
|
1112
|
+
]
|
|
1113
|
+
})]
|
|
1114
|
+
}),
|
|
1115
|
+
status.automation.enabled ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1116
|
+
className: "dsm-workbuddy-xdpool-auto-jobs",
|
|
1117
|
+
children: AUTOMATION_JOBS.map((kind) => {
|
|
1118
|
+
const job = automationJob(status, kind);
|
|
1119
|
+
const hours = automationHours(status, kind);
|
|
1120
|
+
const label = t?.(`row.autoJob_${kind}`) ?? kind;
|
|
1121
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1122
|
+
className: "dsm-workbuddy-xdpool-auto-job",
|
|
1123
|
+
children: [
|
|
1124
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1125
|
+
className: "dsm-workbuddy-xdpool-auto-job-name",
|
|
1126
|
+
children: label
|
|
1127
|
+
}),
|
|
1128
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1129
|
+
className: "dsm-workbuddy-xdpool-auto-job-when",
|
|
1130
|
+
children: hours.length === 0 ? t?.("row.autoHourNone") ?? "not scheduled" : hours.map((hour) => `${String(hour).padStart(2, "0")}:00`).join(" · ")
|
|
1131
|
+
}),
|
|
1132
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1133
|
+
className: "dsm-workbuddy-xdpool-auto-job-last",
|
|
1134
|
+
children: job?.lastRunDate === void 0 ? t?.("row.autoNever") ?? "not run yet" : `${job.lastRunDate} · ${job.ok}${job.failed > 0 ? `/${job.failed}` : ""}`
|
|
1135
|
+
})
|
|
1136
|
+
]
|
|
1137
|
+
}, kind);
|
|
1138
|
+
})
|
|
1139
|
+
}) : null
|
|
1140
|
+
]
|
|
1141
|
+
}),
|
|
821
1142
|
flash === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
822
1143
|
className: "dsm-workbuddy-xdpool-note",
|
|
823
1144
|
children: flash
|
|
@@ -899,6 +1220,9 @@ window.__ModuleLoader__.load({
|
|
|
899
1220
|
onClaimCheckin: (accountId) => {
|
|
900
1221
|
claimCheckin(accountId);
|
|
901
1222
|
},
|
|
1223
|
+
onSaveCreditReserve: (accountId, reserve) => {
|
|
1224
|
+
saveCreditReserve(accountId, reserve);
|
|
1225
|
+
},
|
|
902
1226
|
onToggleDisabled: (accountId, disabled) => {
|
|
903
1227
|
toggleAccountDisabled(accountId, disabled);
|
|
904
1228
|
},
|
|
@@ -964,7 +1288,7 @@ window.__ModuleLoader__.load({
|
|
|
964
1288
|
});
|
|
965
1289
|
}
|
|
966
1290
|
/** One account block: label + status tag + meta + optional credit panels. */
|
|
967
|
-
function AccountBlock({ account, t, checkinBusyId, onClaimCheckin, accountBusyId, onToggleDisabled }) {
|
|
1291
|
+
function AccountBlock({ account, t, checkinBusyId, onClaimCheckin, accountBusyId, onToggleDisabled, onSaveCreditReserve, reserveBusyId }) {
|
|
968
1292
|
const isDisabled = account.disabled === true;
|
|
969
1293
|
const isCooling = account.cooling === true;
|
|
970
1294
|
const cooldownUntil = account.cooldownUntil !== void 0 ? Date.parse(account.cooldownUntil) : void 0;
|
|
@@ -1001,38 +1325,78 @@ window.__ModuleLoader__.load({
|
|
|
1001
1325
|
]
|
|
1002
1326
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1003
1327
|
className: "dsm-workbuddy-xdpool-account-body",
|
|
1004
|
-
children: [
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1328
|
+
children: [
|
|
1329
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1330
|
+
className: "dsm-workbuddy-xdpool-account-copy",
|
|
1331
|
+
children: [
|
|
1332
|
+
account.expiresAt !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1333
|
+
className: "dsm-workbuddy-xdpool-account-meta",
|
|
1334
|
+
children: t?.("row.tokenExpiry", { time: formatDateTime(account.expiresAt) }) ?? `token ${formatDateTime(account.expiresAt)}`
|
|
1335
|
+
}) : null,
|
|
1336
|
+
isCooling && cooldownUntil !== void 0 && !Number.isNaN(cooldownUntil) ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1337
|
+
className: "dsm-workbuddy-xdpool-account-meta",
|
|
1338
|
+
children: [
|
|
1339
|
+
t?.("row.cooldownUntil", { time: formatTime(cooldownUntil) }) ?? `until ${formatTime(cooldownUntil)}`,
|
|
1340
|
+
" · ",
|
|
1341
|
+
t?.("row.cooldownHits", { hits: account.rateLimitHits ?? 0 }) ?? `${account.rateLimitHits ?? 0} hit(s)`
|
|
1342
|
+
]
|
|
1343
|
+
}) : null,
|
|
1344
|
+
modelCooldowns.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1345
|
+
className: "dsm-workbuddy-xdpool-account-modelcool",
|
|
1346
|
+
children: modelCooldowns.map((mc) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1347
|
+
className: "dsm-workbuddy-xdpool-account-modelcool-chip",
|
|
1348
|
+
children: t?.("row.modelCooling", {
|
|
1349
|
+
model: mc.modelId,
|
|
1350
|
+
time: formatDateTime(mc.until)
|
|
1351
|
+
}) ?? `${mc.modelId} cooling to ${formatDateTime(mc.until)}`
|
|
1352
|
+
}, mc.modelId))
|
|
1353
|
+
}) : null
|
|
1354
|
+
]
|
|
1355
|
+
}),
|
|
1356
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(AccountStats, {
|
|
1357
|
+
account,
|
|
1358
|
+
t,
|
|
1359
|
+
checkinBusy: checkinBusyId === account.id,
|
|
1360
|
+
onClaim: onClaimCheckin
|
|
1361
|
+
}),
|
|
1362
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(CreditReserveRow, {
|
|
1363
|
+
account,
|
|
1364
|
+
t,
|
|
1365
|
+
busy: reserveBusyId === account.id,
|
|
1366
|
+
onSave: onSaveCreditReserve
|
|
1367
|
+
}),
|
|
1368
|
+
account.automationToday === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1369
|
+
className: "dsm-workbuddy-xdpool-earned",
|
|
1370
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1371
|
+
className: "dsm-workbuddy-xdpool-earned-label",
|
|
1372
|
+
children: t?.("row.autoEarned") ?? "Automation today"
|
|
1373
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1374
|
+
className: "dsm-workbuddy-xdpool-earned-list",
|
|
1013
1375
|
children: [
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1376
|
+
account.automationToday.credit > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1377
|
+
className: "dsm-workbuddy-xdpool-earned-row",
|
|
1378
|
+
children: t?.("row.autoFromTasks", {
|
|
1379
|
+
credit: account.automationToday.credit,
|
|
1380
|
+
energy: account.automationToday.energy,
|
|
1381
|
+
count: account.automationToday.claimed
|
|
1382
|
+
}) ?? `Tasks +${account.automationToday.credit}`
|
|
1383
|
+
}) : null,
|
|
1384
|
+
account.automationToday.checkinCredit > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1385
|
+
className: "dsm-workbuddy-xdpool-earned-row",
|
|
1386
|
+
children: t?.("row.autoFromCheckin", { credit: account.automationToday.checkinCredit }) ?? `Check-in +${account.automationToday.checkinCredit}`
|
|
1387
|
+
}) : null,
|
|
1388
|
+
account.automationToday.bonusCredit > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1389
|
+
className: "dsm-workbuddy-xdpool-earned-row",
|
|
1390
|
+
children: t?.("row.autoFromBonus", { credit: account.automationToday.bonusCredit }) ?? `Streak +${account.automationToday.bonusCredit}`
|
|
1391
|
+
}) : null,
|
|
1392
|
+
account.automationToday.travelCredit > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1393
|
+
className: "dsm-workbuddy-xdpool-earned-row",
|
|
1394
|
+
children: t?.("row.autoFromTravel", { credit: account.automationToday.travelCredit }) ?? `Buddy +${account.automationToday.travelCredit}`
|
|
1395
|
+
}) : null
|
|
1017
1396
|
]
|
|
1018
|
-
})
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
children: modelCooldowns.map((mc) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1022
|
-
className: "dsm-workbuddy-xdpool-account-modelcool-chip",
|
|
1023
|
-
children: t?.("row.modelCooling", {
|
|
1024
|
-
model: mc.modelId,
|
|
1025
|
-
time: formatDateTime(mc.until)
|
|
1026
|
-
}) ?? `${mc.modelId} cooling to ${formatDateTime(mc.until)}`
|
|
1027
|
-
}, mc.modelId))
|
|
1028
|
-
}) : null
|
|
1029
|
-
]
|
|
1030
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AccountStats, {
|
|
1031
|
-
account,
|
|
1032
|
-
t,
|
|
1033
|
-
checkinBusy: checkinBusyId === account.id,
|
|
1034
|
-
onClaim: onClaimCheckin
|
|
1035
|
-
})]
|
|
1397
|
+
})]
|
|
1398
|
+
})
|
|
1399
|
+
]
|
|
1036
1400
|
})]
|
|
1037
1401
|
});
|
|
1038
1402
|
}
|
|
@@ -1047,6 +1411,61 @@ window.__ModuleLoader__.load({
|
|
|
1047
1411
|
* layout the LaoDing plugin family uses, so the numbers stay scannable and the
|
|
1048
1412
|
* claim button sits where the eye already is.
|
|
1049
1413
|
*/
|
|
1414
|
+
/**
|
|
1415
|
+
* Reserved-credit control for one account.
|
|
1416
|
+
*
|
|
1417
|
+
* The value is committed on blur or Enter rather than on every keystroke:
|
|
1418
|
+
* each save is a settings write plus a status refresh, and a per-character
|
|
1419
|
+
* save would hammer both.
|
|
1420
|
+
*/
|
|
1421
|
+
function CreditReserveRow({ account, t, busy, onSave }) {
|
|
1422
|
+
const [draft, setDraft] = (0, react.useState)(String(account.creditReserve ?? 0));
|
|
1423
|
+
(0, react.useEffect)(() => {
|
|
1424
|
+
setDraft(String(account.creditReserve ?? 0));
|
|
1425
|
+
}, [account.creditReserve]);
|
|
1426
|
+
const commit = () => {
|
|
1427
|
+
const parsed = Number.parseInt(draft, 10);
|
|
1428
|
+
const next = Number.isFinite(parsed) && parsed > 0 ? Math.floor(parsed) : 0;
|
|
1429
|
+
if (next === (account.creditReserve ?? 0)) {
|
|
1430
|
+
setDraft(String(next));
|
|
1431
|
+
return;
|
|
1432
|
+
}
|
|
1433
|
+
onSave(account.id, next);
|
|
1434
|
+
};
|
|
1435
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1436
|
+
className: "dsm-workbuddy-xdpool-reserve",
|
|
1437
|
+
children: [
|
|
1438
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1439
|
+
className: "dsm-workbuddy-xdpool-reserve-label",
|
|
1440
|
+
children: t?.("row.reserveTitle") ?? "Keep at least"
|
|
1441
|
+
}),
|
|
1442
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
1443
|
+
type: "number",
|
|
1444
|
+
min: 0,
|
|
1445
|
+
step: 1,
|
|
1446
|
+
value: draft,
|
|
1447
|
+
disabled: busy,
|
|
1448
|
+
className: "dsm-workbuddy-xdpool-reserve-input",
|
|
1449
|
+
"aria-label": t?.("row.reserveTitle") ?? "Keep at least",
|
|
1450
|
+
onChange: (event) => {
|
|
1451
|
+
setDraft(event.target.value);
|
|
1452
|
+
},
|
|
1453
|
+
onBlur: commit,
|
|
1454
|
+
onKeyDown: (event) => {
|
|
1455
|
+
if (event.key === "Enter") event.target.blur();
|
|
1456
|
+
}
|
|
1457
|
+
}),
|
|
1458
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1459
|
+
className: "dsm-workbuddy-xdpool-reserve-unit",
|
|
1460
|
+
children: busy ? t?.("row.reserveSaving") ?? "Saving…" : t?.("row.reserveUnit") ?? "credits"
|
|
1461
|
+
}),
|
|
1462
|
+
account.reserved === true ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1463
|
+
className: "dsm-workbuddy-xdpool-reserve-badge",
|
|
1464
|
+
children: t?.("row.reserveHolding") ?? "Reserved: skipped"
|
|
1465
|
+
}) : null
|
|
1466
|
+
]
|
|
1467
|
+
});
|
|
1468
|
+
}
|
|
1050
1469
|
function AccountStats({ account, t, checkinBusy, onClaim }) {
|
|
1051
1470
|
const credits = account.credits;
|
|
1052
1471
|
const checkin = account.checkin;
|
|
@@ -1331,19 +1750,54 @@ window.__ModuleLoader__.load({
|
|
|
1331
1750
|
"row.imageCapable": "image input",
|
|
1332
1751
|
"row.rate": "{rate}x credits",
|
|
1333
1752
|
"row.accountsRescan": "Detect accounts again",
|
|
1753
|
+
"row.accountsScanning": "Detecting…",
|
|
1334
1754
|
"row.distTitle": "Account usage",
|
|
1335
1755
|
"row.distPriority": "Priority",
|
|
1336
|
-
"row.distPriorityHint": "
|
|
1756
|
+
"row.distPriorityHint": "Use one account until it runs out, then move to the next",
|
|
1337
1757
|
"row.distRoundRobin": "Round-robin",
|
|
1338
|
-
"row.distRoundRobinHint": "
|
|
1758
|
+
"row.distRoundRobinHint": "Take turns in order, spreading the spend evenly",
|
|
1339
1759
|
"row.distBalanced": "Balanced",
|
|
1340
|
-
"row.distBalancedHint": "Draw
|
|
1341
|
-
"row.accountsScanning": "Detecting…",
|
|
1760
|
+
"row.distBalancedHint": "Draw at random, favouring the account idle longest",
|
|
1342
1761
|
"row.resetCooldowns": "Clear all cooldowns",
|
|
1343
1762
|
"row.resetCooldownsBusy": "Clearing…",
|
|
1344
1763
|
"row.resetCooldownsDone": "Cooldowns cleared",
|
|
1345
1764
|
"row.accountsRescanned": "Detected {count} account(s)",
|
|
1346
|
-
"row.error": "Pool status unavailable: {message}"
|
|
1765
|
+
"row.error": "Pool status unavailable: {message}",
|
|
1766
|
+
"row.autoTitle": "Automation",
|
|
1767
|
+
"row.autoOn": "On",
|
|
1768
|
+
"row.autoOff": "Off",
|
|
1769
|
+
"row.autoBusy": "Saving…",
|
|
1770
|
+
"row.autoHintOn": "Reports activity, claims task rewards and checks in once a day.",
|
|
1771
|
+
"row.autoHintOff": "Off: no background requests are made for you.",
|
|
1772
|
+
"row.autoJob_report": "Activity report",
|
|
1773
|
+
"row.autoJob_tasks": "Task rewards",
|
|
1774
|
+
"row.autoJob_checkin": "Daily check-in",
|
|
1775
|
+
"row.autoJob_streak": "Streak bonus",
|
|
1776
|
+
"row.autoHourNone": "not scheduled",
|
|
1777
|
+
"row.autoNever": "not run yet",
|
|
1778
|
+
"row.autoRun": "Run now",
|
|
1779
|
+
"row.autoRunning": "Running…",
|
|
1780
|
+
"row.autoRan": "Done: {count} account(s) ok, {failed} failed",
|
|
1781
|
+
"row.autoRanTasks": "Done: {claimed} task(s) claimed, +{credit} credits, +{energy} energy",
|
|
1782
|
+
"row.reserveTitle": "Keep at least",
|
|
1783
|
+
"row.reserveUnit": "credits",
|
|
1784
|
+
"row.reserveSaving": "Saving…",
|
|
1785
|
+
"row.reserveHolding": "Reserved: skipped",
|
|
1786
|
+
"row.reserveSaved": "Keeping {credits} credits",
|
|
1787
|
+
"row.reserveCleared": "Reserve cleared",
|
|
1788
|
+
"row.autoToday": "Today",
|
|
1789
|
+
"row.autoEarned": "Automation today",
|
|
1790
|
+
"row.autoEnergy": "energy",
|
|
1791
|
+
"row.autoTasksClaimed": "{count} task(s)",
|
|
1792
|
+
"row.autoRunAll": "Run now",
|
|
1793
|
+
"row.autoRunDone": "Automation pass finished",
|
|
1794
|
+
"row.autoRunTimeout": "Still running; check back in a moment",
|
|
1795
|
+
"row.autoAlreadyRunning": "A run is already in progress",
|
|
1796
|
+
"row.autoRanAll": "Ran {jobs} job(s), {ok} ok, {failed} failed",
|
|
1797
|
+
"row.autoFromTasks": "Tasks +{credit} credits · +{energy} energy · {count} task(s)",
|
|
1798
|
+
"row.autoFromCheckin": "Check-in +{credit} credits",
|
|
1799
|
+
"row.autoFromBonus": "Streak bonus +{credit} credits",
|
|
1800
|
+
"row.autoFromTravel": "Buddy travel +{credit} credits"
|
|
1347
1801
|
};
|
|
1348
1802
|
const zh = {
|
|
1349
1803
|
"row.title": "WorkBuddy 池(dsh-workbuddy-xdpool)",
|
|
@@ -1424,19 +1878,54 @@ window.__ModuleLoader__.load({
|
|
|
1424
1878
|
"row.imageCapable": "图片输入",
|
|
1425
1879
|
"row.rate": "{rate}x 积分",
|
|
1426
1880
|
"row.accountsRescan": "重新检测账号",
|
|
1881
|
+
"row.accountsScanning": "正在检测…",
|
|
1427
1882
|
"row.distTitle": "账号使用方式",
|
|
1428
1883
|
"row.distPriority": "优先模式",
|
|
1429
|
-
"row.distPriorityHint": "
|
|
1884
|
+
"row.distPriorityHint": "先用完一个账号,用完再换下一个",
|
|
1430
1885
|
"row.distRoundRobin": "轮换模式",
|
|
1431
|
-
"row.distRoundRobinHint": "
|
|
1432
|
-
"row.distBalanced": "
|
|
1433
|
-
"row.distBalancedHint": "
|
|
1434
|
-
"row.accountsScanning": "正在检测…",
|
|
1886
|
+
"row.distRoundRobinHint": "按顺序轮流使用,积分均匀分摊",
|
|
1887
|
+
"row.distBalanced": "均衡模式",
|
|
1888
|
+
"row.distBalancedHint": "随机抽取,闲置越久的账号被选中概率越高",
|
|
1435
1889
|
"row.resetCooldowns": "清除所有冷却",
|
|
1436
1890
|
"row.resetCooldownsBusy": "正在清除…",
|
|
1437
1891
|
"row.resetCooldownsDone": "冷却已清除",
|
|
1438
1892
|
"row.accountsRescanned": "检测到 {count} 个账号",
|
|
1439
|
-
"row.error": "池状态不可用:{message}"
|
|
1893
|
+
"row.error": "池状态不可用:{message}",
|
|
1894
|
+
"row.autoTitle": "积分自动化",
|
|
1895
|
+
"row.autoOn": "已开启",
|
|
1896
|
+
"row.autoOff": "已关闭",
|
|
1897
|
+
"row.autoBusy": "保存中…",
|
|
1898
|
+
"row.autoHintOn": "每天自动活跃上报、领取任务奖励并签到。",
|
|
1899
|
+
"row.autoHintOff": "已关闭:不会替你发起任何后台请求。",
|
|
1900
|
+
"row.autoJob_report": "活跃上报",
|
|
1901
|
+
"row.autoJob_tasks": "任务奖励",
|
|
1902
|
+
"row.autoJob_checkin": "每日签到",
|
|
1903
|
+
"row.autoJob_streak": "连登奖励",
|
|
1904
|
+
"row.autoHourNone": "未排程",
|
|
1905
|
+
"row.autoNever": "尚未执行",
|
|
1906
|
+
"row.autoRun": "立即运行",
|
|
1907
|
+
"row.autoRunning": "运行中…",
|
|
1908
|
+
"row.autoRan": "完成:{count} 个账号正常,{failed} 个失败",
|
|
1909
|
+
"row.autoRanTasks": "完成:领取 {claimed} 个任务,+{credit} 积分,+{energy} 能量",
|
|
1910
|
+
"row.reserveTitle": "保留积分",
|
|
1911
|
+
"row.reserveUnit": "积分",
|
|
1912
|
+
"row.reserveSaving": "保存中…",
|
|
1913
|
+
"row.reserveHolding": "已保留·暂停使用",
|
|
1914
|
+
"row.reserveSaved": "已保留 {credits} 积分",
|
|
1915
|
+
"row.reserveCleared": "已取消保留",
|
|
1916
|
+
"row.autoToday": "今日自动化",
|
|
1917
|
+
"row.autoEarned": "今日自动化获得",
|
|
1918
|
+
"row.autoEnergy": "能量",
|
|
1919
|
+
"row.autoTasksClaimed": "{count} 个任务",
|
|
1920
|
+
"row.autoRunAll": "立即运行",
|
|
1921
|
+
"row.autoRunDone": "自动化已执行完成",
|
|
1922
|
+
"row.autoRunTimeout": "仍在执行中,稍后查看结果",
|
|
1923
|
+
"row.autoAlreadyRunning": "已有一次执行正在进行",
|
|
1924
|
+
"row.autoRanAll": "已运行 {jobs} 项,{ok} 个正常,{failed} 个失败",
|
|
1925
|
+
"row.autoFromTasks": "任务 +{credit} 积分 · +{energy} 能量 · {count} 个",
|
|
1926
|
+
"row.autoFromCheckin": "签到 +{credit} 积分",
|
|
1927
|
+
"row.autoFromBonus": "连登奖励 +{credit} 积分",
|
|
1928
|
+
"row.autoFromTravel": "猫猫旅行 +{credit} 积分"
|
|
1440
1929
|
};
|
|
1441
1930
|
//#endregion
|
|
1442
1931
|
//#region src/client/index.tsx
|