diff --git a/sidepanel/contribution-content-update-service.js b/sidepanel/contribution-content-update-service.js index 53db4e1..ba158fe 100644 --- a/sidepanel/contribution-content-update-service.js +++ b/sidepanel/contribution-content-update-service.js @@ -8,11 +8,12 @@ return { slug: String(item?.slug || '').trim(), title: String(item?.title || '').trim(), - isEnabled: Boolean(item?.is_enabled), - hasContent: Boolean(item?.has_content), - isVisible: Boolean(item?.is_visible), - updatedAt: String(item?.updated_at || '').trim(), - updatedAtDisplay: String(item?.updated_at_display || '').trim(), + text: String(item?.text || '').trim(), + isEnabled: Boolean(item?.is_enabled ?? item?.isEnabled), + hasContent: Boolean(item?.has_content ?? item?.hasContent), + isVisible: Boolean(item?.is_visible ?? item?.isVisible), + updatedAt: String(item?.updated_at ?? item?.updatedAt ?? '').trim(), + updatedAtDisplay: String(item?.updated_at_display ?? item?.updatedAtDisplay ?? '').trim(), }; } diff --git a/sidepanel/sidepanel.js b/sidepanel/sidepanel.js index 98d6ef9..89e747f 100644 --- a/sidepanel/sidepanel.js +++ b/sidepanel/sidepanel.js @@ -2854,6 +2854,15 @@ function getContributionUpdatePromptLines(snapshot = currentContributionContentS } const items = Array.isArray(snapshot.items) ? snapshot.items : []; + const autoRunNoticeItem = items.find((item) => + item + && String(item.slug || '').trim().toLowerCase() === 'auto_run_notice' + ); + if (autoRunNoticeItem) { + const noticeText = String(autoRunNoticeItem.text || '').trim(); + return autoRunNoticeItem.isVisible && noticeText ? [noticeText] : []; + } + const hasAnnouncementOrTutorial = items.some((item) => item && item.isVisible @@ -2875,35 +2884,6 @@ function getContributionUpdatePromptLines(snapshot = currentContributionContentS return lines; } -function shouldPromptContributionUpdateBeforeAutoRun(snapshot = currentContributionContentSnapshot) { - const promptVersion = String(snapshot?.promptVersion || '').trim(); - if (!promptVersion) { - return false; - } - if (promptVersion === getDismissedContributionContentPromptVersion()) { - return false; - } - return getContributionUpdatePromptLines(snapshot).length > 0; -} - -async function maybeConfirmContributionUpdateBeforeAutoRun(snapshot = currentContributionContentSnapshot) { - if (!shouldPromptContributionUpdateBeforeAutoRun(snapshot)) { - return true; - } - - const confirmed = await openConfirmModal({ - title: '自动前提醒', - message: getContributionUpdateHintMessage(snapshot), - confirmLabel: '确定继续', - confirmVariant: 'btn-primary', - }); - if (!confirmed) { - return false; - } - dismissContributionUpdateHint(); - return true; -} - function positionContributionUpdateHint() { if (!contributionUpdateLayer || !contributionUpdateHint || !btnContributionMode) { return; @@ -2943,6 +2923,9 @@ function shouldShowContributionUpdateHint(snapshot = currentContributionContentS if (!promptVersion) { return false; } + if (!getContributionUpdatePromptLines(snapshot).length) { + return false; + } if (promptVersion === getDismissedContributionContentPromptVersion()) { return false; } @@ -4651,18 +4634,12 @@ autoStartModal?.addEventListener('click', (event) => { btnAutoStartClose?.addEventListener('click', () => resolveModalChoice(null)); async function startAutoRunFromCurrentSettings() { - let contributionSnapshot = null; try { - contributionSnapshot = await refreshContributionContentHint(); + await refreshContributionContentHint(); } catch (error) { console.warn('Failed to refresh contribution content hint before auto run:', error); } - const confirmedContributionUpdate = await maybeConfirmContributionUpdateBeforeAutoRun(contributionSnapshot); - if (!confirmedContributionUpdate) { - return false; - } - if (typeof settingsDirty !== 'undefined' && settingsDirty && typeof saveSettings === 'function') { await saveSettings({ silent: true }); } diff --git a/tests/contribution-content-update-service.test.js b/tests/contribution-content-update-service.test.js index 65bf266..8e4fdcd 100644 --- a/tests/contribution-content-update-service.test.js +++ b/tests/contribution-content-update-service.test.js @@ -79,23 +79,15 @@ test('getContentUpdateSnapshot returns a prompt version for visible contribution async json() { return { ok: true, - prompt_version: 'announcement:2026-04-21T12:00:00Z|tutorial:2026-04-21T12:05:00Z', + prompt_version: 'auto_run_notice:2026-04-21T12:05:00Z', has_visible_updates: true, latest_updated_at: '2026-04-21T12:05:00Z', latest_updated_at_display: '2026-04-21 20:05', items: [ { - slug: 'announcement', - title: '最新公告', - is_enabled: true, - has_content: true, - is_visible: true, - updated_at: '2026-04-21T12:00:00Z', - updated_at_display: '2026-04-21 20:00', - }, - { - slug: 'tutorial', - title: '使用教程', + slug: 'auto_run_notice', + title: '自动提示', + text: '公告和使用教程更新了,可点上方“贡献/使用教程”查看。', is_enabled: true, has_content: true, is_visible: true, @@ -111,13 +103,13 @@ test('getContentUpdateSnapshot returns a prompt version for visible contribution const snapshot = await api.getContentUpdateSnapshot(); assert.equal(snapshot.status, 'update-available'); - assert.equal(snapshot.promptVersion, 'announcement:2026-04-21T12:00:00Z|tutorial:2026-04-21T12:05:00Z'); + assert.equal(snapshot.promptVersion, 'auto_run_notice:2026-04-21T12:05:00Z'); assert.equal(snapshot.hasVisibleUpdates, true); assert.equal(snapshot.latestUpdatedAt, '2026-04-21T12:05:00Z'); - assert.equal(snapshot.items.length, 2); + assert.equal(snapshot.items.length, 1); assert.deepEqual( - snapshot.items.map((item) => [item.slug, item.isVisible]), - [['announcement', true], ['tutorial', true]] + snapshot.items.map((item) => [item.slug, item.isVisible, item.text]), + [['auto_run_notice', true, '公告和使用教程更新了,可点上方“贡献/使用教程”查看。']] ); }); diff --git a/tests/sidepanel-auto-run-content-refresh.test.js b/tests/sidepanel-auto-run-content-refresh.test.js index e908664..5258fcf 100644 --- a/tests/sidepanel-auto-run-content-refresh.test.js +++ b/tests/sidepanel-auto-run-content-refresh.test.js @@ -50,8 +50,6 @@ function extractFunction(name) { function createApi({ refreshImpl, - confirmImpl, - dismissImpl, runCount = 3, plusModeEnabled = false, plusRiskEnabled = false, @@ -119,14 +117,6 @@ async function refreshContributionContentHint() { events.push({ type: 'refresh' }); ${refreshImpl ? 'return (' + refreshImpl + ')();' : 'return null;'} } -async function maybeConfirmContributionUpdateBeforeAutoRun(snapshot) { - events.push({ type: 'confirm-check', snapshot }); - ${confirmImpl ? 'return (' + confirmImpl + ')(snapshot);' : 'return true;'} -} -function dismissContributionUpdateHint() { - events.push({ type: 'dismiss-hint' }); - ${dismissImpl ? '(' + dismissImpl + ')();' : ''} -} ${bundle} return { startAutoRunFromCurrentSettings, @@ -145,9 +135,9 @@ test('startAutoRunFromCurrentSettings refreshes contribution content hint before assert.equal(result, true); assert.deepEqual( api.getEvents().map((entry) => entry.type), - ['refresh', 'confirm-check', 'send'] + ['refresh', 'send'] ); - assert.equal(api.getEvents()[2].message.type, 'AUTO_RUN'); + assert.equal(api.getEvents()[1].message.type, 'AUTO_RUN'); }); test('startAutoRunFromCurrentSettings continues auto run when contribution content refresh fails', async () => { @@ -161,27 +151,26 @@ test('startAutoRunFromCurrentSettings continues auto run when contribution conte assert.equal(result, true); assert.deepEqual( events.map((entry) => entry.type), - ['refresh', 'warn', 'confirm-check', 'send'] + ['refresh', 'warn', 'send'] ); assert.match(String(events[1].args[0]), /Failed to refresh contribution content hint before auto run/); - assert.equal(events[3].message.type, 'AUTO_RUN'); + assert.equal(events[2].message.type, 'AUTO_RUN'); }); -test('startAutoRunFromCurrentSettings aborts when contribution update confirmation is declined', async () => { +test('startAutoRunFromCurrentSettings does not block auto run when contribution content has updates', async () => { const api = createApi({ refreshImpl: `async () => ({ promptVersion: 'questionnaire:2026-04-23T00:00:00Z', items: [{ slug: 'questionnaire', isVisible: true }], })`, - confirmImpl: 'async () => false', }); const result = await api.startAutoRunFromCurrentSettings(); - assert.equal(result, false); + assert.equal(result, true); assert.deepEqual( api.getEvents().map((entry) => entry.type), - ['refresh', 'confirm-check'] + ['refresh', 'send'] ); }); @@ -198,10 +187,10 @@ test('startAutoRunFromCurrentSettings shows Plus risk warning before starting mo assert.equal(result, true); assert.deepEqual( events.map((entry) => entry.type), - ['refresh', 'confirm-check', 'plus-risk-modal', 'send'] + ['refresh', 'plus-risk-modal', 'send'] ); - assert.equal(events[2].totalRuns, 4); - assert.equal(events[3].message.payload.totalRuns, 4); + assert.equal(events[1].totalRuns, 4); + assert.equal(events[2].message.payload.totalRuns, 4); }); test('startAutoRunFromCurrentSettings aborts when Plus risk warning is declined', async () => { @@ -217,7 +206,7 @@ test('startAutoRunFromCurrentSettings aborts when Plus risk warning is declined' assert.equal(result, false); assert.deepEqual( api.getEvents().map((entry) => entry.type), - ['refresh', 'confirm-check', 'plus-risk-modal'] + ['refresh', 'plus-risk-modal'] ); }); @@ -235,7 +224,7 @@ test('startAutoRunFromCurrentSettings aborts when Plus contribution prompt opens assert.equal(result, false); assert.deepEqual( api.getEvents().map((entry) => entry.type), - ['refresh', 'confirm-check', 'plus-contribution-modal'] + ['refresh', 'plus-contribution-modal'] ); - assert.equal(api.getEvents()[2].plusModeEnabled, true); + assert.equal(api.getEvents()[1].plusModeEnabled, true); }); diff --git a/tests/sidepanel-contribution-update-hint.test.js b/tests/sidepanel-contribution-update-hint.test.js index 6592dfa..b0cfd3b 100644 --- a/tests/sidepanel-contribution-update-hint.test.js +++ b/tests/sidepanel-contribution-update-hint.test.js @@ -86,3 +86,36 @@ test('getContributionUpdateHintMessage returns questionnaire prompt alone when o assert.equal(message, '有新的征求意见,请佬友共同参与选择。'); }); + +test('getContributionUpdateHintMessage uses managed auto run notice text when available', () => { + const message = api.getContributionUpdateHintMessage({ + promptVersion: 'auto_run_notice:2026-04-23T00:00:01Z', + items: [ + { + slug: 'auto_run_notice', + isVisible: true, + text: '公告和使用教程更新了,可点上方“贡献/使用教程”查看。', + }, + { slug: 'announcement', isVisible: true }, + { slug: 'questionnaire', isVisible: true }, + ], + }); + + assert.equal(message, '公告和使用教程更新了,可点上方“贡献/使用教程”查看。'); +}); + +test('getContributionUpdateHintMessage suppresses managed auto run notice when it is disabled', () => { + const message = api.getContributionUpdateHintMessage({ + promptVersion: 'announcement:2026-04-23T00:00:00Z', + items: [ + { + slug: 'auto_run_notice', + isVisible: false, + text: '公告和使用教程更新了,可点上方“贡献/使用教程”查看。', + }, + { slug: 'announcement', isVisible: true }, + ], + }); + + assert.equal(message, ''); +});