feat: 添加贡献更新提示层,优化贡献模式按钮及相关提示功能
This commit is contained in:
+13
-11
@@ -243,33 +243,35 @@ header {
|
|||||||
color: var(--orange);
|
color: var(--orange);
|
||||||
}
|
}
|
||||||
|
|
||||||
.contribution-entry {
|
.contribution-update-layer {
|
||||||
display: flex;
|
position: fixed;
|
||||||
flex-direction: column;
|
inset: 0;
|
||||||
align-items: flex-start;
|
pointer-events: none;
|
||||||
gap: 6px;
|
z-index: 1400;
|
||||||
position: relative;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.contribution-update-hint {
|
.contribution-update-hint {
|
||||||
position: relative;
|
--contribution-update-arrow-left: 20px;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
max-width: 220px;
|
max-width: min(220px, calc(100vw - 24px));
|
||||||
margin-left: 6px;
|
|
||||||
padding: 8px 10px;
|
padding: 8px 10px;
|
||||||
background: color-mix(in srgb, var(--amber) 10%, var(--bg-base));
|
background: color-mix(in srgb, var(--amber) 10%, var(--bg-base));
|
||||||
border: 1px solid color-mix(in srgb, var(--amber) 34%, var(--border));
|
border: 1px solid color-mix(in srgb, var(--amber) 34%, var(--border));
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
box-shadow: var(--shadow-sm);
|
box-shadow: var(--shadow-sm);
|
||||||
|
pointer-events: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.contribution-update-hint::before {
|
.contribution-update-hint::before {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -7px;
|
top: -7px;
|
||||||
left: 14px;
|
left: calc(var(--contribution-update-arrow-left) - 6px);
|
||||||
width: 12px;
|
width: 12px;
|
||||||
height: 12px;
|
height: 12px;
|
||||||
background: inherit;
|
background: inherit;
|
||||||
@@ -436,7 +438,7 @@ header {
|
|||||||
|
|
||||||
.run-group {
|
.run-group {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: center;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-11
@@ -34,17 +34,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="header-btns">
|
<div class="header-btns">
|
||||||
<div class="run-group">
|
<div class="run-group">
|
||||||
<div class="contribution-entry">
|
<button id="btn-contribution-mode" class="btn btn-outline btn-sm btn-contribution-mode" type="button"
|
||||||
<button id="btn-contribution-mode" class="btn btn-outline btn-sm btn-contribution-mode" type="button"
|
aria-pressed="false" title="进入贡献模式并打开上传页">贡献/使用</button>
|
||||||
aria-pressed="false" title="进入贡献模式并打开上传页">贡献/使用</button>
|
|
||||||
<div id="contribution-update-hint" class="contribution-update-hint" aria-live="polite" hidden>
|
|
||||||
<p id="contribution-update-hint-text" class="contribution-update-hint-text">
|
|
||||||
公告 / 使用教程有更新了,可点上方“贡献/使用”查看。
|
|
||||||
</p>
|
|
||||||
<button id="btn-dismiss-contribution-update-hint" class="contribution-update-hint-close" type="button"
|
|
||||||
aria-label="关闭更新提示" title="关闭更新提示">×</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<input type="number" id="input-run-count" class="run-count-input" value="1" min="1" max="50" title="运行次数" />
|
<input type="number" id="input-run-count" class="run-count-input" value="1" min="1" max="50" title="运行次数" />
|
||||||
<button id="btn-auto-run" class="btn btn-success" title="自动执行全部步骤">
|
<button id="btn-auto-run" class="btn btn-success" title="自动执行全部步骤">
|
||||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
|
||||||
@@ -90,6 +81,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
<div id="contribution-update-layer" class="contribution-update-layer" hidden>
|
||||||
|
<div id="contribution-update-hint" class="contribution-update-hint" aria-live="polite" hidden>
|
||||||
|
<p id="contribution-update-hint-text" class="contribution-update-hint-text">
|
||||||
|
公告 / 使用教程有更新了,可点上方“贡献/使用”查看。
|
||||||
|
</p>
|
||||||
|
<button id="btn-dismiss-contribution-update-hint" class="contribution-update-hint-close" type="button"
|
||||||
|
aria-label="关闭更新提示" title="关闭更新提示">×</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<section id="update-section" hidden>
|
<section id="update-section" hidden>
|
||||||
<div class="update-card">
|
<div class="update-card">
|
||||||
<div class="update-card-header">
|
<div class="update-card-header">
|
||||||
|
|||||||
+48
-2
@@ -57,6 +57,7 @@ const btnSaveSettings = document.getElementById('btn-save-settings');
|
|||||||
const btnStop = document.getElementById('btn-stop');
|
const btnStop = document.getElementById('btn-stop');
|
||||||
const btnReset = document.getElementById('btn-reset');
|
const btnReset = document.getElementById('btn-reset');
|
||||||
const btnContributionMode = document.getElementById('btn-contribution-mode');
|
const btnContributionMode = document.getElementById('btn-contribution-mode');
|
||||||
|
const contributionUpdateLayer = document.getElementById('contribution-update-layer');
|
||||||
const contributionUpdateHint = document.getElementById('contribution-update-hint');
|
const contributionUpdateHint = document.getElementById('contribution-update-hint');
|
||||||
const contributionUpdateHintText = document.getElementById('contribution-update-hint-text');
|
const contributionUpdateHintText = document.getElementById('contribution-update-hint-text');
|
||||||
const btnDismissContributionUpdateHint = document.getElementById('btn-dismiss-contribution-update-hint');
|
const btnDismissContributionUpdateHint = document.getElementById('btn-dismiss-contribution-update-hint');
|
||||||
@@ -2220,9 +2221,40 @@ function getContributionUpdateHintMessage(snapshot = currentContributionContentS
|
|||||||
return '公告 / 使用教程有更新了,可点上方“贡献/使用”查看。';
|
return '公告 / 使用教程有更新了,可点上方“贡献/使用”查看。';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function positionContributionUpdateHint() {
|
||||||
|
if (!contributionUpdateLayer || !contributionUpdateHint || !btnContributionMode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (contributionUpdateLayer.hidden || contributionUpdateHint.hidden) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const buttonRect = btnContributionMode.getBoundingClientRect();
|
||||||
|
const viewportWidth = Math.max(document.documentElement?.clientWidth || 0, window.innerWidth || 0);
|
||||||
|
const viewportHeight = Math.max(document.documentElement?.clientHeight || 0, window.innerHeight || 0);
|
||||||
|
const hintWidth = contributionUpdateHint.offsetWidth || 220;
|
||||||
|
const hintHeight = contributionUpdateHint.offsetHeight || 56;
|
||||||
|
const viewportPadding = 12;
|
||||||
|
const gap = 10;
|
||||||
|
|
||||||
|
const maxLeft = Math.max(viewportPadding, viewportWidth - hintWidth - viewportPadding);
|
||||||
|
const left = Math.min(Math.max(viewportPadding, Math.round(buttonRect.left)), maxLeft);
|
||||||
|
const shouldPlaceAbove = (buttonRect.bottom + gap + hintHeight) > (viewportHeight - viewportPadding)
|
||||||
|
&& buttonRect.top > (hintHeight + gap + viewportPadding);
|
||||||
|
const top = shouldPlaceAbove
|
||||||
|
? Math.max(viewportPadding, Math.round(buttonRect.top - hintHeight - gap))
|
||||||
|
: Math.max(viewportPadding, Math.round(buttonRect.bottom + gap));
|
||||||
|
const buttonCenter = Math.round(buttonRect.left + (buttonRect.width / 2));
|
||||||
|
const arrowOffset = Math.min(Math.max(16, buttonCenter - left), Math.max(16, hintWidth - 16));
|
||||||
|
|
||||||
|
contributionUpdateHint.style.left = `${left}px`;
|
||||||
|
contributionUpdateHint.style.top = `${top}px`;
|
||||||
|
contributionUpdateHint.style.setProperty('--contribution-update-arrow-left', `${arrowOffset}px`);
|
||||||
|
}
|
||||||
|
|
||||||
function shouldShowContributionUpdateHint(snapshot = currentContributionContentSnapshot) {
|
function shouldShowContributionUpdateHint(snapshot = currentContributionContentSnapshot) {
|
||||||
const promptVersion = String(snapshot?.promptVersion || '').trim();
|
const promptVersion = String(snapshot?.promptVersion || '').trim();
|
||||||
if (!contributionUpdateHint || !contributionUpdateHintText || !btnContributionMode) {
|
if (!contributionUpdateLayer || !contributionUpdateHint || !contributionUpdateHintText || !btnContributionMode) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!promptVersion) {
|
if (!promptVersion) {
|
||||||
@@ -2238,17 +2270,23 @@ function shouldShowContributionUpdateHint(snapshot = currentContributionContentS
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderContributionUpdateHint(snapshot = currentContributionContentSnapshot) {
|
function renderContributionUpdateHint(snapshot = currentContributionContentSnapshot) {
|
||||||
if (!contributionUpdateHint) {
|
if (!contributionUpdateLayer || !contributionUpdateHint) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const visible = shouldShowContributionUpdateHint(snapshot);
|
const visible = shouldShowContributionUpdateHint(snapshot);
|
||||||
|
contributionUpdateLayer.hidden = !visible;
|
||||||
contributionUpdateHint.hidden = !visible;
|
contributionUpdateHint.hidden = !visible;
|
||||||
if (!visible || !contributionUpdateHintText) {
|
if (!visible || !contributionUpdateHintText) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
contributionUpdateHintText.textContent = getContributionUpdateHintMessage(snapshot);
|
contributionUpdateHintText.textContent = getContributionUpdateHintMessage(snapshot);
|
||||||
|
if (typeof window.requestAnimationFrame === 'function') {
|
||||||
|
window.requestAnimationFrame(() => positionContributionUpdateHint());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
positionContributionUpdateHint();
|
||||||
}
|
}
|
||||||
|
|
||||||
function dismissContributionUpdateHint() {
|
function dismissContributionUpdateHint() {
|
||||||
@@ -4692,6 +4730,14 @@ document.addEventListener('keydown', (event) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
positionContributionUpdateHint();
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener('scroll', () => {
|
||||||
|
positionContributionUpdateHint();
|
||||||
|
}, true);
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Init
|
// Init
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ test('sidepanel html keeps a single contribution mode button in header', () => {
|
|||||||
assert.equal(matches.length, 1);
|
assert.equal(matches.length, 1);
|
||||||
assert.match(html, /id="btn-contribution-mode"[^>]*title="进入贡献模式并打开上传页"/);
|
assert.match(html, /id="btn-contribution-mode"[^>]*title="进入贡献模式并打开上传页"/);
|
||||||
assert.match(html, />贡献\/使用<\/button>/);
|
assert.match(html, />贡献\/使用<\/button>/);
|
||||||
|
assert.match(html, /<\/header>\s*<div id="contribution-update-layer"/);
|
||||||
|
assert.match(html, /id="contribution-update-layer"/);
|
||||||
assert.match(html, /id="contribution-update-hint"/);
|
assert.match(html, /id="contribution-update-hint"/);
|
||||||
assert.match(html, /id="contribution-update-hint-text"/);
|
assert.match(html, /id="contribution-update-hint-text"/);
|
||||||
assert.match(html, /id="btn-dismiss-contribution-update-hint"/);
|
assert.match(html, /id="btn-dismiss-contribution-update-hint"/);
|
||||||
|
|||||||
Reference in New Issue
Block a user