feat: 更新贡献内容服务,增强自动运行通知逻辑和测试用例
This commit is contained in:
@@ -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(),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+13
-36
@@ -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 });
|
||||
}
|
||||
|
||||
@@ -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, '公告和使用教程更新了,可点上方“贡献/使用教程”查看。']]
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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, '');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user