feat(viewer): share sheet with QR code + link + copy (replaces inline toast, App-style)
- ShareSheet.vue: bottom sheet (mobile) / centered card (desktop) — QR canvas (qrcode dep), selectable deep link, copy with on-button feedback (2.5s), optional navigator.share button, Esc/scrim/close dismiss, focus on open - AlbumHeader + PhotoLightbox: share buttons open the sheet (album URL / photo deep link); page-level copied strips removed - tests rewritten for sheet behavior — viewer 244 green Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -597,7 +597,12 @@ describe('photo lightbox interactions (UI-02 V05)', () => {
|
||||
expect(current.value).toBe('p2');
|
||||
});
|
||||
|
||||
it('shares via navigator.share with the album title and photo deep link; success is silent', async () => {
|
||||
/** 分享弹层(Teleport 到 body):从 document 定位。 */
|
||||
function lbSheet(): HTMLElement | null {
|
||||
return document.querySelector('.share-sheet');
|
||||
}
|
||||
|
||||
it('share opens the sheet with the photo deep link; native share via sheet button', async () => {
|
||||
const share = vi.fn(() => Promise.resolve());
|
||||
Object.defineProperty(navigator, 'share', { value: share, configurable: true });
|
||||
const { wrapper } = mountV05('p1', {
|
||||
@@ -608,12 +613,20 @@ describe('photo lightbox interactions (UI-02 V05)', () => {
|
||||
|
||||
await wrapper.find('button[aria-label="分享照片"]').trigger('click');
|
||||
await flushPromises();
|
||||
expect(share).toHaveBeenCalledWith({ title: '2026 公司年会', url: '/a/tok-lb/p/p1?lang=zh-CN' });
|
||||
// 原生分享成功:无应用内轻提示(面板已收尾,§5.4)。
|
||||
// 弹层出现并携带照片深链(页面级提示已退役)。
|
||||
expect(lbSheet()).not.toBeNull();
|
||||
expect(
|
||||
lbSheet()!.querySelector('[data-test="share-sheet-url"]')!.textContent,
|
||||
).toBe('/a/tok-lb/p/p1?lang=zh-CN');
|
||||
expect(wrapper.find('.share-status').exists()).toBe(false);
|
||||
|
||||
const nativeBtn = lbSheet()!.querySelector<HTMLButtonElement>('[data-test="share-sheet-native"]')!;
|
||||
nativeBtn.click();
|
||||
await flushPromises();
|
||||
expect(share).toHaveBeenCalledWith({ title: '2026 公司年会', url: '/a/tok-lb/p/p1?lang=zh-CN' });
|
||||
});
|
||||
|
||||
it('falls back to the clipboard with feedback when native share is unavailable', async () => {
|
||||
it('sheet copy button writes the deep link with on-button feedback', async () => {
|
||||
const writeText = vi.fn(() => Promise.resolve());
|
||||
Object.defineProperty(navigator, 'clipboard', { value: { writeText }, configurable: true });
|
||||
const { wrapper } = mountV05('p1', { shareUrl: '/a/tok-lb/p/p1?lang=zh-CN' });
|
||||
@@ -621,8 +634,11 @@ describe('photo lightbox interactions (UI-02 V05)', () => {
|
||||
|
||||
await wrapper.find('button[aria-label="分享照片"]').trigger('click');
|
||||
await flushPromises();
|
||||
const copyBtn = lbSheet()!.querySelector<HTMLButtonElement>('[data-test="share-sheet-copy"]')!;
|
||||
copyBtn.click();
|
||||
await flushPromises();
|
||||
expect(writeText).toHaveBeenCalledWith('/a/tok-lb/p/p1?lang=zh-CN');
|
||||
expect(wrapper.find('.share-status').text()).toContain('链接已复制');
|
||||
expect(copyBtn.textContent).toContain('已复制');
|
||||
});
|
||||
|
||||
it('shows the download failure only on the photo that triggered it', async () => {
|
||||
|
||||
Reference in New Issue
Block a user