Merge branch 'dev' into icloud-forward-mailbox-config

This commit is contained in:
que01
2026-04-26 14:44:29 +08:00
committed by GitHub
56 changed files with 6828 additions and 626 deletions
+41 -8
View File
@@ -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);
+16
View File
@@ -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);
+27 -5
View File
@@ -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
View File
@@ -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;