feat(viewer,ui04): E05 realtime hearts + effect-demo alignment (initial offset, heart params, decode gate, bidirectional manual scroll)
- reactions.ts pure fns: delta->hearts sampling, burstId dedupe (TTL/capacity), pending-visible cache (5s/50), 250ms emission throttle with merge - useEmbedReactions: read-only RealtimeClient subscription on album.publicToken (no viewer-page side effects, A15), rebind teardown, 10s grace disconnect, no fake bubbles on WS failure - ReactionLayer: demo-frozen heart effect (12/16/20 sizes, two colors, 110px rise, 1.6s ease-out, 300ms stagger, max 8, drop-shadow) in unscoped block (created elements lack scoped hash) - demo alignment: initial offset 32px, decode+500ms startup gate, 1:1 drag, arrows +-40, focus-tip, bidirectional manual scroll (manualScroll), loader handle 100x44 exact styles, <=599px offset default 12 - tests: +8 reactions unit (244 viewer), e2e E05: real cross-context like -> heart on correct photo (EMB-A09), zero likes/visits submission (EMB-A15), 16s hearts recording Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -95,8 +95,8 @@ import {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 收起把手(§2.4):白底胶囊、蓝色相机图标 + 照片/Photos 文案;全部
|
||||
// inline style(零宿主 CSS 污染);有效点击区 ≥44×44。
|
||||
// 收起把手(§2.4;效果示例 .handle 精确值):100×44 白底胶囊、圆角 22、
|
||||
// 1px #e3eaf2 边、蓝图标 16 + 12px 文案;全部 inline style(零宿主污染)。
|
||||
function createHandle(inst) {
|
||||
var h = document.createElement('div');
|
||||
h.setAttribute('role', 'button');
|
||||
@@ -105,24 +105,24 @@ import {
|
||||
var s = h.style;
|
||||
s.position = 'fixed';
|
||||
s.height = HANDLE_MIN + 'px';
|
||||
s.minWidth = '88px';
|
||||
s.width = '100px';
|
||||
s.boxSizing = 'border-box';
|
||||
s.padding = '0 16px';
|
||||
s.borderRadius = '22px';
|
||||
s.border = '1px solid #e3eaf2';
|
||||
s.background = '#ffffff';
|
||||
s.boxShadow = '0 2px 10px rgba(15,23,42,0.18)';
|
||||
s.boxShadow = '0 4px 16px rgba(15,23,42,0.125)';
|
||||
s.zIndex = String(inst.config.zIndex);
|
||||
s.cursor = 'pointer';
|
||||
s.display = 'flex';
|
||||
s.alignItems = 'center';
|
||||
s.justifyContent = 'center';
|
||||
s.gap = '6px';
|
||||
s.font = '500 12px/1 system-ui, -apple-system, "Segoe UI", "PingFang SC", sans-serif';
|
||||
s.color = '#1A73E8';
|
||||
s.gap = '8px';
|
||||
s.font = '400 12px/1 system-ui, -apple-system, "Segoe UI", "PingFang SC", sans-serif';
|
||||
s.color = '#32618e';
|
||||
s.whiteSpace = 'nowrap';
|
||||
h.innerHTML =
|
||||
'<svg viewBox="0 0 24 24" width="16" height="16" aria-hidden="true" focusable="false">' +
|
||||
'<path fill="#1A73E8" d="M9 2 7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z"/></svg>' +
|
||||
'<svg viewBox="0 0 24 24" width="16" height="16" aria-hidden="true" focusable="false" style="color:#1a73e8">' +
|
||||
'<path fill="currentColor" d="M9 2 7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z"/></svg>' +
|
||||
'<span>' + (isZh(inst.config.lang) ? '照片' : 'Photos') + '</span>';
|
||||
function activate(ev) {
|
||||
if (ev.type === 'keydown') {
|
||||
@@ -153,11 +153,12 @@ import {
|
||||
return inst.collapsed ? HANDLE_MIN : inst.height;
|
||||
}
|
||||
|
||||
/** 默认水平偏移:未配置时桌面 16 / 窄屏 12(§2.1)。data-* 显式或后台
|
||||
* 配置到达后(offsetConfigured)按配置值。 */
|
||||
/** 默认水平偏移:未配置时桌面 16 / ≤599px 视口 12(§2.1;效果示例
|
||||
* media(max-width:599px) 档)。data-* 显式或后台配置到达后
|
||||
* (offsetConfigured)按配置值。 */
|
||||
function effectiveOffsetX(inst) {
|
||||
if (inst.config.explicit.offsetX || inst.offsetConfigured) return inst.config.offsetX;
|
||||
return inst.narrow ? 12 : 16;
|
||||
return w.innerWidth <= 599 ? 12 : 16;
|
||||
}
|
||||
|
||||
/** wrapper 几何:W=min(195,可用宽)、H=min(280,可用高);不足操作下限时
|
||||
|
||||
Reference in New Issue
Block a user