Merge branch 'dev' into icloud-forward-mailbox-config
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
(function attachSidepanelContributionMode(globalScope) {
|
||||
const ACTIVE_STATUSES = new Set(['started', 'waiting', 'processing']);
|
||||
const FINAL_STATUSES = new Set(['auto_approved', 'auto_rejected', 'manual_review_required', 'expired', 'error']);
|
||||
const DEFAULT_COPY = '当前账号将用于支持项目维护。扩展会自动申请贡献登录地址并持续跟踪授权状态;如检测到回调地址,会自动提交,并继续等待 CPA 最终确认。';
|
||||
(function attachSidepanelContributionMode(globalScope) {
|
||||
const ACTIVE_STATUSES = new Set(['started', 'waiting', 'processing']);
|
||||
const FINAL_STATUSES = new Set(['auto_approved', 'auto_rejected', 'expired', 'error']);
|
||||
const DEFAULT_COPY = '当前账号将用于支持项目维护。扩展会自动申请贡献登录地址并持续跟踪授权状态;如检测到回调地址,会自动提交,并继续等待服务端确认。';
|
||||
const CONTRIBUTION_SOURCE_CPA = 'cpa';
|
||||
const CONTRIBUTION_SOURCE_SUB2API = 'sub2api';
|
||||
const CONTRIBUTION_SUB2API_DEFAULT_GROUP_NAME = 'codex号池';
|
||||
|
||||
function createContributionModeManager(context = {}) {
|
||||
const {
|
||||
@@ -66,6 +69,21 @@
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeContributionSource(value = '') {
|
||||
const normalized = normalizeString(value).toLowerCase();
|
||||
return normalized === CONTRIBUTION_SOURCE_SUB2API
|
||||
? CONTRIBUTION_SOURCE_SUB2API
|
||||
: CONTRIBUTION_SOURCE_CPA;
|
||||
}
|
||||
|
||||
function getContributionSource(currentState = getLatestState()) {
|
||||
return normalizeContributionSource(currentState.contributionSource || currentState.panelMode);
|
||||
}
|
||||
|
||||
function getContributionSourceLabel(currentState = getLatestState()) {
|
||||
return getContributionSource(currentState) === CONTRIBUTION_SOURCE_SUB2API ? 'SUB2API' : 'CPA';
|
||||
}
|
||||
|
||||
function isContributionModeEnabled(currentState = getLatestState()) {
|
||||
return Boolean(currentState.contributionMode);
|
||||
}
|
||||
@@ -140,7 +158,7 @@
|
||||
if (status === 'waiting') {
|
||||
return '等待提交回调';
|
||||
}
|
||||
if (status === 'processing' || status === 'auto_approved' || status === 'auto_rejected' || status === 'manual_review_required') {
|
||||
if (status === 'processing' || status === 'auto_approved' || status === 'auto_rejected') {
|
||||
return status === 'processing' ? '已提交回调' : '授权已结束';
|
||||
}
|
||||
if (status === 'expired' || status === 'error') {
|
||||
@@ -173,7 +191,15 @@
|
||||
}
|
||||
|
||||
function getSummaryText(currentState = getLatestState()) {
|
||||
return normalizeString(currentState.contributionStatusMessage) || DEFAULT_COPY;
|
||||
const statusMessage = normalizeString(currentState.contributionStatusMessage);
|
||||
if (statusMessage) {
|
||||
return statusMessage;
|
||||
}
|
||||
if (getContributionSource(currentState) === CONTRIBUTION_SOURCE_SUB2API) {
|
||||
const groupName = normalizeString(currentState.contributionTargetGroupName) || CONTRIBUTION_SUB2API_DEFAULT_GROUP_NAME;
|
||||
return `当前账号将用于支持项目维护。贡献会通过 SUB2API 完成,并固定写入 ${groupName} 分组;如检测到回调地址,扩展会自动提交并等待服务端确认。`;
|
||||
}
|
||||
return DEFAULT_COPY;
|
||||
}
|
||||
|
||||
function getContributionPortalPageUrl() {
|
||||
@@ -310,9 +336,10 @@
|
||||
const enabled = isContributionModeEnabled(currentState);
|
||||
const blocked = isModeSwitchBlocked();
|
||||
const activeElement = typeof document !== 'undefined' ? document.activeElement : null;
|
||||
const sourceLabel = getContributionSourceLabel(currentState);
|
||||
|
||||
if (enabled && dom.selectPanelMode) {
|
||||
dom.selectPanelMode.value = 'cpa';
|
||||
dom.selectPanelMode.value = getContributionSource(currentState);
|
||||
}
|
||||
|
||||
helpers.updatePanelModeUI?.();
|
||||
@@ -322,7 +349,13 @@
|
||||
dom.contributionModePanel.hidden = !enabled;
|
||||
}
|
||||
if (dom.contributionModeText) {
|
||||
dom.contributionModeText.textContent = DEFAULT_COPY;
|
||||
dom.contributionModeText.textContent = getSummaryText({
|
||||
contributionSource: currentState.contributionSource,
|
||||
contributionTargetGroupName: currentState.contributionTargetGroupName,
|
||||
});
|
||||
}
|
||||
if (dom.contributionModeBadge) {
|
||||
dom.contributionModeBadge.textContent = enabled ? sourceLabel : '';
|
||||
}
|
||||
if (dom.inputContributionNickname && activeElement !== dom.inputContributionNickname) {
|
||||
const nextNickname = normalizeString(currentState.contributionNickname);
|
||||
|
||||
@@ -2419,6 +2419,22 @@ header {
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
.plus-contribution-prompt-copy {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.plus-contribution-prompt-image {
|
||||
display: block;
|
||||
width: min(220px, 100%);
|
||||
max-height: 280px;
|
||||
object-fit: contain;
|
||||
margin: 12px auto 0;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
background: var(--bg-primary);
|
||||
}
|
||||
|
||||
.modal-message a,
|
||||
.modal-alert a {
|
||||
color: var(--blue);
|
||||
|
||||
@@ -115,11 +115,11 @@
|
||||
<option value="codex2api">Codex2API</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="contribution-mode-panel" class="contribution-mode-panel" hidden>
|
||||
<div class="contribution-mode-panel-header">
|
||||
<span class="section-label">贡献模式</span>
|
||||
<span class="contribution-mode-badge">CPA</span>
|
||||
</div>
|
||||
<div id="contribution-mode-panel" class="contribution-mode-panel" hidden>
|
||||
<div class="contribution-mode-panel-header">
|
||||
<span class="section-label">贡献模式</span>
|
||||
<span id="contribution-mode-badge" class="contribution-mode-badge">CPA</span>
|
||||
</div>
|
||||
<p id="contribution-mode-text" class="contribution-mode-text">
|
||||
当前账号将用于支持项目维护。扩展会自动申请贡献登录地址并持续跟踪授权状态;如检测到回调地址,会自动提交,无需手动复制。</p>
|
||||
<div class="data-row contribution-mode-field">
|
||||
@@ -212,6 +212,28 @@
|
||||
<button id="btn-toggle-password" class="input-icon-btn" type="button" aria-label="显示密码" title="显示密码"></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="data-row" id="row-plus-mode">
|
||||
<span class="data-label">Plus 模式</span>
|
||||
<div class="data-inline setting-pair">
|
||||
<div class="setting-group setting-group-primary">
|
||||
<label class="toggle-switch" for="input-plus-mode-enabled" title="开启后使用 Plus Checkout + PayPal 授权流程">
|
||||
<input type="checkbox" id="input-plus-mode-enabled" />
|
||||
<span class="toggle-switch-track" aria-hidden="true">
|
||||
<span class="toggle-switch-thumb"></span>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<span class="setting-caption">PayPal 订阅链路</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="data-row" id="row-paypal-email" style="display:none;">
|
||||
<span class="data-label">PayPal 账号</span>
|
||||
<input type="text" id="input-paypal-email" class="data-input" placeholder="请输入 PayPal 登录邮箱" />
|
||||
</div>
|
||||
<div class="data-row" id="row-paypal-password" style="display:none;">
|
||||
<span class="data-label">PayPal 密码</span>
|
||||
<input type="password" id="input-paypal-password" class="data-input" placeholder="请输入 PayPal 登录密码" />
|
||||
</div>
|
||||
<div class="data-row">
|
||||
<span class="data-label">邮箱服务</span>
|
||||
<div class="data-inline">
|
||||
|
||||
+326
-16
@@ -34,6 +34,7 @@ const updateReleaseList = document.getElementById('update-release-list');
|
||||
const btnOpenRelease = document.getElementById('btn-open-release');
|
||||
const settingsCard = document.getElementById('settings-card');
|
||||
const contributionModePanel = document.getElementById('contribution-mode-panel');
|
||||
const contributionModeBadge = document.getElementById('contribution-mode-badge');
|
||||
const contributionModeText = document.getElementById('contribution-mode-text');
|
||||
const inputContributionNickname = document.getElementById('input-contribution-nickname');
|
||||
const inputContributionQq = document.getElementById('input-contribution-qq');
|
||||
@@ -99,6 +100,12 @@ const inputCodex2ApiUrl = document.getElementById('input-codex2api-url');
|
||||
const rowCodex2ApiAdminKey = document.getElementById('row-codex2api-admin-key');
|
||||
const inputCodex2ApiAdminKey = document.getElementById('input-codex2api-admin-key');
|
||||
const rowCustomPassword = document.getElementById('row-custom-password');
|
||||
const rowPlusMode = document.getElementById('row-plus-mode');
|
||||
const inputPlusModeEnabled = document.getElementById('input-plus-mode-enabled');
|
||||
const rowPaypalEmail = document.getElementById('row-paypal-email');
|
||||
const inputPaypalEmail = document.getElementById('input-paypal-email');
|
||||
const rowPaypalPassword = document.getElementById('row-paypal-password');
|
||||
const inputPaypalPassword = document.getElementById('input-paypal-password');
|
||||
const selectMailProvider = document.getElementById('select-mail-provider');
|
||||
const btnMailLogin = document.getElementById('btn-mail-login');
|
||||
const rowCustomMailProviderPool = document.getElementById('row-custom-mail-provider-pool');
|
||||
@@ -248,11 +255,12 @@ const btnAutoStartCancel = document.getElementById('btn-auto-start-cancel');
|
||||
const btnAutoStartRestart = document.getElementById('btn-auto-start-restart');
|
||||
const btnAutoStartContinue = document.getElementById('btn-auto-start-continue');
|
||||
const autoHintText = document.querySelector('.auto-hint');
|
||||
const stepDefinitions = (window.MultiPageStepDefinitions?.getSteps?.() || []).sort((left, right) => left.order - right.order);
|
||||
const STEP_IDS = stepDefinitions.map((step) => Number(step.id)).filter(Number.isFinite);
|
||||
const STEP_DEFAULT_STATUSES = Object.fromEntries(STEP_IDS.map((stepId) => [stepId, 'pending']));
|
||||
const SKIPPABLE_STEPS = new Set(STEP_IDS);
|
||||
const stepsList = document.querySelector('.steps-list');
|
||||
let currentPlusModeEnabled = false;
|
||||
let stepDefinitions = getStepDefinitionsForMode(false);
|
||||
let STEP_IDS = stepDefinitions.map((step) => Number(step.id)).filter(Number.isFinite);
|
||||
let STEP_DEFAULT_STATUSES = Object.fromEntries(STEP_IDS.map((stepId) => [stepId, 'pending']));
|
||||
let SKIPPABLE_STEPS = new Set(STEP_IDS);
|
||||
const AUTO_DELAY_MIN_MINUTES = 1;
|
||||
const AUTO_DELAY_MAX_MINUTES = 1440;
|
||||
const AUTO_DELAY_DEFAULT_MINUTES = 30;
|
||||
@@ -273,8 +281,32 @@ const DEFAULT_MAIL_2925_MODE = MAIL_2925_MODE_PROVIDE;
|
||||
const NEW_USER_GUIDE_PROMPT_DISMISSED_STORAGE_KEY = 'multipage-new-user-guide-prompt-dismissed';
|
||||
const AUTO_SKIP_FAILURES_PROMPT_DISMISSED_STORAGE_KEY = 'multipage-auto-skip-failures-prompt-dismissed';
|
||||
const AUTO_RUN_FALLBACK_RISK_PROMPT_DISMISSED_STORAGE_KEY = 'multipage-auto-run-fallback-risk-prompt-dismissed';
|
||||
const AUTO_RUN_PLUS_RISK_PROMPT_DISMISSED_STORAGE_KEY = 'multipage-auto-run-plus-risk-prompt-dismissed';
|
||||
const PLUS_CONTRIBUTION_PROMPT_LEDGER_STORAGE_KEY = 'multipage-plus-contribution-prompt-ledger';
|
||||
|
||||
function getStepDefinitionsForMode(plusModeEnabled = false) {
|
||||
return (window.MultiPageStepDefinitions?.getSteps?.({ plusModeEnabled }) || [])
|
||||
.sort((left, right) => {
|
||||
const leftOrder = Number.isFinite(left.order) ? left.order : left.id;
|
||||
const rightOrder = Number.isFinite(right.order) ? right.order : right.id;
|
||||
if (leftOrder !== rightOrder) return leftOrder - rightOrder;
|
||||
return left.id - right.id;
|
||||
});
|
||||
}
|
||||
|
||||
function rebuildStepDefinitionState(plusModeEnabled = false) {
|
||||
currentPlusModeEnabled = Boolean(plusModeEnabled);
|
||||
stepDefinitions = getStepDefinitionsForMode(currentPlusModeEnabled);
|
||||
STEP_IDS = stepDefinitions.map((step) => Number(step.id)).filter(Number.isFinite);
|
||||
STEP_DEFAULT_STATUSES = Object.fromEntries(STEP_IDS.map((stepId) => [stepId, 'pending']));
|
||||
SKIPPABLE_STEPS = new Set(STEP_IDS);
|
||||
}
|
||||
const CONTRIBUTION_CONTENT_PROMPT_DISMISSED_VERSION_STORAGE_KEY = 'multipage-contribution-content-prompt-dismissed-version';
|
||||
const AUTO_RUN_FALLBACK_RISK_WARNING_MIN_RUNS = 3;
|
||||
const AUTO_RUN_PLUS_RISK_WARNING_MAX_SAFE_RUNS = 3;
|
||||
const PLUS_CONTRIBUTION_PROMPT_THRESHOLD = 5;
|
||||
const PLUS_CONTRIBUTION_ACCOUNT_CREDIT = 5;
|
||||
const PLUS_CONTRIBUTION_DONATION_CREDIT = 20;
|
||||
const HOTMAIL_SERVICE_MODE_REMOTE = 'remote';
|
||||
const HOTMAIL_SERVICE_MODE_LOCAL = 'local';
|
||||
const ICLOUD_PROVIDER = 'icloud';
|
||||
@@ -1021,10 +1053,164 @@ function setAutoRunFallbackRiskPromptDismissed(dismissed) {
|
||||
setPromptDismissed(AUTO_RUN_FALLBACK_RISK_PROMPT_DISMISSED_STORAGE_KEY, dismissed);
|
||||
}
|
||||
|
||||
function isAutoRunPlusRiskPromptDismissed() {
|
||||
return isPromptDismissed(AUTO_RUN_PLUS_RISK_PROMPT_DISMISSED_STORAGE_KEY);
|
||||
}
|
||||
|
||||
function setAutoRunPlusRiskPromptDismissed(dismissed) {
|
||||
setPromptDismissed(AUTO_RUN_PLUS_RISK_PROMPT_DISMISSED_STORAGE_KEY, dismissed);
|
||||
}
|
||||
|
||||
function shouldWarnAutoRunFallbackRisk(totalRuns, autoRunSkipFailures) {
|
||||
return totalRuns >= AUTO_RUN_FALLBACK_RISK_WARNING_MIN_RUNS;
|
||||
}
|
||||
|
||||
function shouldWarnPlusAutoRunRisk(totalRuns, plusModeEnabled) {
|
||||
return Boolean(plusModeEnabled)
|
||||
&& Math.floor(Number(totalRuns) || 0) > AUTO_RUN_PLUS_RISK_WARNING_MAX_SAFE_RUNS;
|
||||
}
|
||||
|
||||
function normalizePlusContributionPromptNumber(value) {
|
||||
const number = Math.floor(Number(value) || 0);
|
||||
return Number.isFinite(number) ? number : 0;
|
||||
}
|
||||
|
||||
function normalizePlusContributionPromptLedger(value = {}) {
|
||||
const source = value && typeof value === 'object' ? value : {};
|
||||
return {
|
||||
promptBaseline: normalizePlusContributionPromptNumber(source.promptBaseline),
|
||||
donationCredit: Math.max(0, normalizePlusContributionPromptNumber(source.donationCredit)),
|
||||
};
|
||||
}
|
||||
|
||||
function getPlusContributionPromptLedger() {
|
||||
try {
|
||||
return normalizePlusContributionPromptLedger(
|
||||
JSON.parse(localStorage.getItem(PLUS_CONTRIBUTION_PROMPT_LEDGER_STORAGE_KEY) || '{}')
|
||||
);
|
||||
} catch {
|
||||
return normalizePlusContributionPromptLedger();
|
||||
}
|
||||
}
|
||||
|
||||
function setPlusContributionPromptLedger(ledger) {
|
||||
localStorage.setItem(
|
||||
PLUS_CONTRIBUTION_PROMPT_LEDGER_STORAGE_KEY,
|
||||
JSON.stringify(normalizePlusContributionPromptLedger(ledger))
|
||||
);
|
||||
}
|
||||
|
||||
function isSuccessfulPlusAccountRecord(record = {}) {
|
||||
return record?.finalStatus === 'success' && Boolean(record.plusModeEnabled);
|
||||
}
|
||||
|
||||
function getPlusContributionPromptTotals(records = []) {
|
||||
return (Array.isArray(records) ? records : []).reduce((totals, record) => {
|
||||
if (!isSuccessfulPlusAccountRecord(record)) {
|
||||
return totals;
|
||||
}
|
||||
if (record.contributionMode) {
|
||||
totals.contributionSuccess += 1;
|
||||
} else {
|
||||
totals.plusSuccess += 1;
|
||||
}
|
||||
return totals;
|
||||
}, {
|
||||
plusSuccess: 0,
|
||||
contributionSuccess: 0,
|
||||
});
|
||||
}
|
||||
|
||||
function getPlusContributionPromptProgress(records = [], ledger = getPlusContributionPromptLedger()) {
|
||||
const totals = getPlusContributionPromptTotals(records);
|
||||
const normalizedLedger = normalizePlusContributionPromptLedger(ledger);
|
||||
const credit = (totals.contributionSuccess * PLUS_CONTRIBUTION_ACCOUNT_CREDIT)
|
||||
+ normalizedLedger.donationCredit;
|
||||
const netCount = totals.plusSuccess - credit;
|
||||
const sinceLastPrompt = netCount - normalizedLedger.promptBaseline;
|
||||
return {
|
||||
...totals,
|
||||
credit,
|
||||
netCount,
|
||||
sinceLastPrompt,
|
||||
shouldPrompt: sinceLastPrompt >= PLUS_CONTRIBUTION_PROMPT_THRESHOLD,
|
||||
};
|
||||
}
|
||||
|
||||
function shouldShowPlusContributionPrompt(records = [], plusModeEnabled = false, ledger = getPlusContributionPromptLedger()) {
|
||||
return Boolean(plusModeEnabled)
|
||||
&& getPlusContributionPromptProgress(records, ledger).shouldPrompt;
|
||||
}
|
||||
|
||||
function markPlusContributionPromptShown(records = [], ledger = getPlusContributionPromptLedger()) {
|
||||
const progress = getPlusContributionPromptProgress(records, ledger);
|
||||
const nextLedger = {
|
||||
...normalizePlusContributionPromptLedger(ledger),
|
||||
promptBaseline: progress.netCount,
|
||||
};
|
||||
setPlusContributionPromptLedger(nextLedger);
|
||||
return nextLedger;
|
||||
}
|
||||
|
||||
function addPlusContributionPromptCredit(credit, ledger = getPlusContributionPromptLedger()) {
|
||||
const normalizedLedger = normalizePlusContributionPromptLedger(ledger);
|
||||
const nextLedger = {
|
||||
...normalizedLedger,
|
||||
donationCredit: normalizedLedger.donationCredit + Math.max(0, normalizePlusContributionPromptNumber(credit)),
|
||||
};
|
||||
setPlusContributionPromptLedger(nextLedger);
|
||||
return nextLedger;
|
||||
}
|
||||
|
||||
function getPlusContributionSupportImageUrl() {
|
||||
if (typeof chrome !== 'undefined' && chrome.runtime?.getURL) {
|
||||
return chrome.runtime.getURL('docs/images/微信.png');
|
||||
}
|
||||
return '../docs/images/微信.png';
|
||||
}
|
||||
|
||||
function buildPlusContributionSupportPromptHtml() {
|
||||
const imageUrl = getPlusContributionSupportImageUrl();
|
||||
return [
|
||||
'<span class="plus-contribution-prompt-copy">您觉得这个 Plus 功能怎么样?您的账户数量应该已经够个人使用啦。</span>',
|
||||
'<span class="plus-contribution-prompt-copy">可以打开贡献给作者贡献几个账号,以便于让作者开发更好的功能出来吗?或者打赏一下作者?</span>',
|
||||
`<img class="plus-contribution-prompt-image" src="${escapeHtml(imageUrl)}" alt="微信打赏二维码" />`,
|
||||
].join('');
|
||||
}
|
||||
|
||||
function openPlusContributionSupportModal() {
|
||||
return openActionModal({
|
||||
title: 'Plus 功能使用反馈',
|
||||
messageHtml: buildPlusContributionSupportPromptHtml(),
|
||||
actions: [
|
||||
{ id: null, label: '取消', variant: 'btn-ghost' },
|
||||
{ id: 'contribute', label: '去贡献账号', variant: 'btn-outline' },
|
||||
{ id: 'donated', label: '已打赏', variant: 'btn-primary' },
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
async function maybeShowPlusContributionPromptBeforeAutoRun(plusModeEnabled) {
|
||||
const records = Array.isArray(latestState?.accountRunHistory) ? latestState.accountRunHistory : [];
|
||||
if (!shouldShowPlusContributionPrompt(records, plusModeEnabled)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const choice = await openPlusContributionSupportModal();
|
||||
const ledger = markPlusContributionPromptShown(records);
|
||||
if (choice === 'donated') {
|
||||
addPlusContributionPromptCredit(PLUS_CONTRIBUTION_DONATION_CREDIT, ledger);
|
||||
showToast('感谢打赏支持,已延后下一次 Plus 提醒。', 'success', 2200);
|
||||
return true;
|
||||
}
|
||||
if (choice === 'contribute') {
|
||||
openExternalUrl(getContributionPortalUrl());
|
||||
showToast('已打开贡献页面,可以按页面提示贡献 Plus 账号。', 'info', 2200);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
async function openAutoSkipFailuresConfirmModal() {
|
||||
const result = await openConfirmModalWithOption({
|
||||
title: '自动重试说明',
|
||||
@@ -1051,6 +1237,19 @@ async function openAutoRunFallbackRiskConfirmModal(totalRuns) {
|
||||
};
|
||||
}
|
||||
|
||||
async function openPlusAutoRunRiskConfirmModal(totalRuns) {
|
||||
const result = await openConfirmModalWithOption({
|
||||
title: 'Plus 自动轮数提醒',
|
||||
message: `Plus 模式下当前设置为 ${totalRuns} 轮。轮数过多可能造成 PayPal 或账号快速封号。建议够用就好:我注册了几个使用,没多注册,完全足够使用,并且没有封号。这个模式下只要可以注册成功就能使用,所以不要贪杯哦。`,
|
||||
confirmLabel: '我知道了,继续',
|
||||
});
|
||||
|
||||
return {
|
||||
confirmed: result.confirmed,
|
||||
dismissPrompt: result.optionChecked,
|
||||
};
|
||||
}
|
||||
|
||||
function updateConfigMenuControls() {
|
||||
const disabled = configActionInFlight || settingsSaveInFlight;
|
||||
const contributionModeEnabled = Boolean(latestState?.contributionMode);
|
||||
@@ -1126,7 +1325,8 @@ function isDoneStatus(status) {
|
||||
}
|
||||
|
||||
function getStepStatuses(state = latestState) {
|
||||
return { ...STEP_DEFAULT_STATUSES, ...(state?.stepStatuses || {}) };
|
||||
const merged = { ...STEP_DEFAULT_STATUSES, ...(state?.stepStatuses || {}) };
|
||||
return Object.fromEntries(STEP_IDS.map((stepId) => [stepId, merged[stepId] || 'pending']));
|
||||
}
|
||||
|
||||
function getFirstUnfinishedStep(state = latestState) {
|
||||
@@ -1713,7 +1913,9 @@ function collectSettingsPayload() {
|
||||
label: typeof DEFAULT_HERO_SMS_COUNTRY_LABEL !== 'undefined' ? DEFAULT_HERO_SMS_COUNTRY_LABEL : 'Thailand',
|
||||
};
|
||||
return {
|
||||
panelMode: selectPanelMode.value,
|
||||
...(contributionModeEnabled ? {} : {
|
||||
panelMode: selectPanelMode.value,
|
||||
}),
|
||||
vpsUrl: inputVpsUrl.value.trim(),
|
||||
vpsPassword: inputVpsPassword.value,
|
||||
localCpaStep9Mode: getSelectedLocalCpaStep9Mode(),
|
||||
@@ -1724,6 +1926,15 @@ function collectSettingsPayload() {
|
||||
sub2apiDefaultProxyName: inputSub2ApiDefaultProxy.value.trim(),
|
||||
codex2apiUrl: inputCodex2ApiUrl.value.trim(),
|
||||
codex2apiAdminKey: inputCodex2ApiAdminKey.value.trim(),
|
||||
plusModeEnabled: typeof inputPlusModeEnabled !== 'undefined' && inputPlusModeEnabled
|
||||
? Boolean(inputPlusModeEnabled.checked)
|
||||
: Boolean(latestState?.plusModeEnabled),
|
||||
paypalEmail: typeof inputPaypalEmail !== 'undefined' && inputPaypalEmail
|
||||
? inputPaypalEmail.value.trim()
|
||||
: String(latestState?.paypalEmail || ''),
|
||||
paypalPassword: typeof inputPaypalPassword !== 'undefined' && inputPaypalPassword
|
||||
? inputPaypalPassword.value
|
||||
: String(latestState?.paypalPassword || ''),
|
||||
...(contributionModeEnabled ? {} : {
|
||||
customPassword: inputPassword.value,
|
||||
}),
|
||||
@@ -1960,6 +2171,21 @@ function updatePhoneVerificationSettingsUI() {
|
||||
});
|
||||
}
|
||||
|
||||
function updatePlusModeUI() {
|
||||
const enabled = typeof inputPlusModeEnabled !== 'undefined' && inputPlusModeEnabled
|
||||
? Boolean(inputPlusModeEnabled.checked)
|
||||
: false;
|
||||
[
|
||||
typeof rowPaypalEmail !== 'undefined' ? rowPaypalEmail : null,
|
||||
typeof rowPaypalPassword !== 'undefined' ? rowPaypalPassword : null,
|
||||
].forEach((row) => {
|
||||
if (!row) {
|
||||
return;
|
||||
}
|
||||
row.style.display = enabled ? '' : 'none';
|
||||
});
|
||||
}
|
||||
|
||||
function setSettingsCardLocked(locked) {
|
||||
if (!settingsCard) {
|
||||
return;
|
||||
@@ -2140,6 +2366,9 @@ function applyAutoRunStatus(payload = currentAutoRun) {
|
||||
|
||||
function initializeManualStepActions() {
|
||||
document.querySelectorAll('.step-row').forEach((row) => {
|
||||
if (row.querySelector('.step-actions')) {
|
||||
return;
|
||||
}
|
||||
const step = Number(row.dataset.step);
|
||||
const statusEl = row.querySelector('.step-status');
|
||||
if (!statusEl) return;
|
||||
@@ -2183,6 +2412,21 @@ function renderStepsList() {
|
||||
if (stepsProgress) {
|
||||
stepsProgress.textContent = `0 / ${STEP_IDS.length}`;
|
||||
}
|
||||
|
||||
initializeManualStepActions();
|
||||
renderStepStatuses();
|
||||
updateButtonStates();
|
||||
}
|
||||
|
||||
function syncStepDefinitionsForMode(plusModeEnabled = false, options = {}) {
|
||||
const nextPlusModeEnabled = Boolean(plusModeEnabled);
|
||||
const shouldRender = Boolean(options.render) || nextPlusModeEnabled !== currentPlusModeEnabled;
|
||||
if (!shouldRender) {
|
||||
return;
|
||||
}
|
||||
|
||||
rebuildStepDefinitionState(nextPlusModeEnabled);
|
||||
renderStepsList();
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
@@ -2190,11 +2434,24 @@ function renderStepsList() {
|
||||
// ============================================================
|
||||
|
||||
function applySettingsState(state) {
|
||||
if (typeof syncStepDefinitionsForMode === 'function') {
|
||||
syncStepDefinitionsForMode(Boolean(state?.plusModeEnabled));
|
||||
}
|
||||
syncLatestState(state);
|
||||
syncAutoRunState(state);
|
||||
renderStepStatuses(latestState);
|
||||
|
||||
inputEmail.value = state?.email || '';
|
||||
syncPasswordField(state || {});
|
||||
if (typeof inputPlusModeEnabled !== 'undefined' && inputPlusModeEnabled) {
|
||||
inputPlusModeEnabled.checked = Boolean(state?.plusModeEnabled);
|
||||
}
|
||||
if (typeof inputPaypalEmail !== 'undefined' && inputPaypalEmail) {
|
||||
inputPaypalEmail.value = state?.paypalEmail || '';
|
||||
}
|
||||
if (typeof inputPaypalPassword !== 'undefined' && inputPaypalPassword) {
|
||||
inputPaypalPassword.value = state?.paypalPassword || '';
|
||||
}
|
||||
inputVpsUrl.value = state?.vpsUrl || '';
|
||||
inputVpsPassword.value = state?.vpsPassword || '';
|
||||
setLocalCpaStep9Mode(state?.localCpaStep9Mode);
|
||||
@@ -2319,6 +2576,9 @@ function applySettingsState(state) {
|
||||
updateFallbackThreadIntervalInputState();
|
||||
updateAccountRunHistorySettingsUI();
|
||||
updatePhoneVerificationSettingsUI();
|
||||
if (typeof updatePlusModeUI === 'function') {
|
||||
updatePlusModeUI();
|
||||
}
|
||||
updatePanelModeUI();
|
||||
updateMailProviderUI();
|
||||
if (isLuckmailProvider(state?.mailProvider)) {
|
||||
@@ -2924,6 +3184,7 @@ function getCustomMailProviderUiCopy() {
|
||||
|
||||
function getCustomVerificationPromptCopy(step) {
|
||||
const verificationLabel = step === 4 ? '注册验证码' : '登录验证码';
|
||||
const isLoginVerificationStep = step === 8 || step === 11;
|
||||
return {
|
||||
title: `手动处理${verificationLabel}`,
|
||||
message: `当前邮箱服务为“自定义邮箱”。请先在页面中手动输入${verificationLabel},并确认已经进入下一页面后,再点击确认。`,
|
||||
@@ -2931,7 +3192,7 @@ function getCustomVerificationPromptCopy(step) {
|
||||
text: `点击确认后会跳过步骤 ${step}。`,
|
||||
tone: 'danger',
|
||||
},
|
||||
...(step === 8 ? {
|
||||
...(isLoginVerificationStep ? {
|
||||
phoneActionLabel: '出现手机号验证',
|
||||
phoneActionAlert: {
|
||||
text: '如果当前页面已经进入手机号验证,可直接标记为失败并继续下一个邮箱。',
|
||||
@@ -2943,7 +3204,7 @@ function getCustomVerificationPromptCopy(step) {
|
||||
|
||||
async function openCustomVerificationConfirmDialog(step) {
|
||||
const promptCopy = getCustomVerificationPromptCopy(step);
|
||||
if (step === 8) {
|
||||
if (step === 8 || step === 11) {
|
||||
return openActionModal({
|
||||
title: promptCopy.title,
|
||||
message: promptCopy.message,
|
||||
@@ -3500,9 +3761,6 @@ function updatePanelModeUI() {
|
||||
// ============================================================
|
||||
|
||||
function updateStepUI(step, status) {
|
||||
const statusEl = document.querySelector(`.step-status[data-step="${step}"]`);
|
||||
const row = document.querySelector(`.step-row[data-step="${step}"]`);
|
||||
|
||||
syncLatestState({
|
||||
stepStatuses: {
|
||||
...getStepStatuses(),
|
||||
@@ -3510,16 +3768,31 @@ function updateStepUI(step, status) {
|
||||
},
|
||||
});
|
||||
|
||||
if (statusEl) statusEl.textContent = STATUS_ICONS[status] || '';
|
||||
if (row) {
|
||||
row.className = `step-row ${status}`;
|
||||
}
|
||||
|
||||
renderSingleStepStatus(step, status);
|
||||
updateButtonStates();
|
||||
updateProgressCounter();
|
||||
updateConfigMenuControls();
|
||||
}
|
||||
|
||||
function renderSingleStepStatus(step, status) {
|
||||
const normalizedStatus = status || 'pending';
|
||||
const statusEl = document.querySelector(`.step-status[data-step="${step}"]`);
|
||||
const row = document.querySelector(`.step-row[data-step="${step}"]`);
|
||||
|
||||
if (statusEl) statusEl.textContent = STATUS_ICONS[normalizedStatus] || '';
|
||||
if (row) {
|
||||
row.className = `step-row ${normalizedStatus}`;
|
||||
}
|
||||
}
|
||||
|
||||
function renderStepStatuses(state = latestState) {
|
||||
const statuses = getStepStatuses(state);
|
||||
for (const step of STEP_IDS) {
|
||||
renderSingleStepStatus(step, statuses[step]);
|
||||
}
|
||||
updateProgressCounter();
|
||||
}
|
||||
|
||||
function updateProgressCounter() {
|
||||
const completed = Object.values(getStepStatuses()).filter(isDoneStatus).length;
|
||||
stepsProgress.textContent = `${completed} / ${STEP_IDS.length}`;
|
||||
@@ -4049,6 +4322,7 @@ const contributionModeManager = window.SidepanelContributionMode?.createContribu
|
||||
btnOpenAccountRecords,
|
||||
btnOpenContributionUpload,
|
||||
btnStartContribution,
|
||||
contributionModeBadge,
|
||||
contributionModePanel,
|
||||
contributionModeSummary,
|
||||
contributionModeText,
|
||||
@@ -4496,6 +4770,9 @@ async function startAutoRunFromCurrentSettings() {
|
||||
if (lockedRunCount > 0) {
|
||||
inputRunCount.value = String(lockedRunCount);
|
||||
}
|
||||
const plusModeEnabled = typeof inputPlusModeEnabled !== 'undefined' && inputPlusModeEnabled
|
||||
? Boolean(inputPlusModeEnabled.checked)
|
||||
: Boolean(currentPlusModeEnabled || latestState?.plusModeEnabled);
|
||||
let mode = 'restart';
|
||||
const autoRunSkipFailures = inputAutoSkipFailures.checked;
|
||||
const contributionNickname = String(inputContributionNickname?.value || '').trim();
|
||||
@@ -4515,6 +4792,11 @@ async function startAutoRunFromCurrentSettings() {
|
||||
mode = choice;
|
||||
}
|
||||
|
||||
const confirmedPlusContributionPrompt = await maybeShowPlusContributionPromptBeforeAutoRun(plusModeEnabled);
|
||||
if (!confirmedPlusContributionPrompt) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (shouldWarnAutoRunFallbackRisk(totalRuns, autoRunSkipFailures)
|
||||
&& !isAutoRunFallbackRiskPromptDismissed()) {
|
||||
const result = await openAutoRunFallbackRiskConfirmModal(totalRuns);
|
||||
@@ -4526,6 +4808,17 @@ async function startAutoRunFromCurrentSettings() {
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldWarnPlusAutoRunRisk(totalRuns, plusModeEnabled)
|
||||
&& !isAutoRunPlusRiskPromptDismissed()) {
|
||||
const result = await openPlusAutoRunRiskConfirmModal(totalRuns);
|
||||
if (!result.confirmed) {
|
||||
return false;
|
||||
}
|
||||
if (result.dismissPrompt) {
|
||||
setAutoRunPlusRiskPromptDismissed(true);
|
||||
}
|
||||
}
|
||||
|
||||
btnAutoRun.disabled = true;
|
||||
inputRunCount.disabled = true;
|
||||
const delayEnabled = inputAutoDelayEnabled.checked;
|
||||
@@ -4742,6 +5035,23 @@ inputPassword.addEventListener('blur', () => {
|
||||
saveSettings({ silent: true }).catch(() => { });
|
||||
});
|
||||
|
||||
inputPlusModeEnabled?.addEventListener('change', () => {
|
||||
updatePlusModeUI();
|
||||
syncStepDefinitionsForMode(Boolean(inputPlusModeEnabled.checked), { render: true });
|
||||
markSettingsDirty(true);
|
||||
saveSettings({ silent: true }).catch(() => { });
|
||||
});
|
||||
|
||||
[inputPaypalEmail, inputPaypalPassword].forEach((input) => {
|
||||
input?.addEventListener('input', () => {
|
||||
markSettingsDirty(true);
|
||||
scheduleSettingsAutoSave();
|
||||
});
|
||||
input?.addEventListener('blur', () => {
|
||||
saveSettings({ silent: true }).catch(() => { });
|
||||
});
|
||||
});
|
||||
|
||||
selectMailProvider.addEventListener('change', async () => {
|
||||
const previousProvider = latestState?.mailProvider || '';
|
||||
const previousMail2925Mode = latestState?.mail2925Mode;
|
||||
|
||||
Reference in New Issue
Block a user