Skip to content

Commit f8e25c8

Browse files
committed
обновлена индикация копирования ссылки на свой список желаний на портале
1 parent 18e7cf3 commit f8e25c8

File tree

16 files changed

+82
-120
lines changed

16 files changed

+82
-120
lines changed

pnpm-lock.yaml

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

portal/CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
# Changelog
22

3+
## 1.6.2 Экипажный контрольный механизм (2025-08-25)
4+
<img width="128" height="128" src="release-images/1.6.2.png"/>
5+
6+
https://github.com/tmible/wishlist/compare/18e7cf3..master
7+
8+
39
## 1.6.1 Зеркальный рассвет (2025-08-25)
410
<img width="128" height="128" src="release-images/1.6.1.png"/>
511

6-
https://github.com/tmible/wishlist/compare/4f66657..master
12+
https://github.com/tmible/wishlist/compare/4f66657..18e7cf3
713

814

915
## 1.6.0 Эхо древнего времени (2025-08-24)

portal/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@tmible/wishlist-portal",
3-
"version": "1.6.1",
3+
"version": "1.6.2",
44
"private": true,
55
"description": "Портал со списками желаний",
66
"repository": {
@@ -77,6 +77,7 @@
7777
"resize-observer-polyfill": "1.5.1",
7878
"svelte": "5.25.2",
7979
"svelte-check": "4.1.5",
80+
"svoast": "3.0.3",
8081
"tailwindcss": "4.0.15",
8182
"tailwindcss-animate": "1.0.7",
8283
"typescript": "5.8.2",

portal/release-images/1.6.2.png

1.89 MB
Loading

portal/src/app.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
:root {
4242
/* disable in favour of using bits-ui ScrollArea */
4343
scrollbar-gutter: auto;
44+
--svoast-offset: calc(var(--spacing) * 6);
4445
}
4546

4647
body {
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<!-- @component Тост -->
2+
<script>
3+
4+
/**
5+
* @typedef {object} Props
6+
* @property {import('svoast').ToastType} type Тип тоста
7+
* @property {string} message Сообщение тоста
8+
*/
9+
10+
/** @type {Props} */
11+
const { type, message } = $props();
12+
</script>
13+
14+
<div
15+
class="alert"
16+
class:alert-info={type === 'info'}
17+
class:alert-success={type === 'success'}
18+
class:alert-warning={type === 'warning'}
19+
class:alert-error={type === 'error'}
20+
>
21+
{message}
22+
</div>
Lines changed: 12 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,26 @@
1-
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
1+
import { toast } from 'svoast';
2+
import { afterEach, describe, expect, it, vi } from 'vitest';
23
import { shareLink } from '../link.service.js';
34

4-
describe('wishlist / link service', () => {
5-
beforeEach(() => {
6-
vi.useFakeTimers();
7-
});
5+
vi.mock('svoast');
86

9-
afterEach(async () => {
10-
await vi.runAllTimersAsync();
11-
vi.useRealTimers();
7+
describe('wishlist / link service', () => {
8+
afterEach(() => {
129
vi.clearAllMocks();
1310
});
1411

1512
describe('link to bot', () => {
1613
it('should share', async () => {
1714
const share = vi.fn();
1815
vi.stubGlobal('navigator', { share });
19-
await shareLink({ classList: { add: vi.fn(), remove: vi.fn() } }, false, 'hash');
16+
await shareLink(false, 'hash');
2017
expect(share).toHaveBeenCalledWith({ url: 'https://t.me/wishnibot?start=hash' });
2118
});
2219

2320
it('should copy link', async () => {
2421
const writeText = vi.fn();
2522
vi.stubGlobal('navigator', { share: vi.fn().mockRejectedValue(), clipboard: { writeText } });
26-
await shareLink({ classList: { add: vi.fn(), remove: vi.fn() } }, false, 'hash');
23+
await shareLink(false, 'hash');
2724
expect(writeText).toHaveBeenCalledWith('https://t.me/wishnibot?start=hash');
2825
});
2926
});
@@ -32,7 +29,7 @@ describe('wishlist / link service', () => {
3229
it('should share', async () => {
3330
const share = vi.fn();
3431
vi.stubGlobal('navigator', { share });
35-
await shareLink({ classList: { add: vi.fn(), remove: vi.fn() } }, true, 'hash');
32+
await shareLink(true, 'hash');
3633
expect(
3734
share,
3835
).toHaveBeenCalledWith(
@@ -43,31 +40,17 @@ describe('wishlist / link service', () => {
4340
it('should copy link', async () => {
4441
const writeText = vi.fn();
4542
vi.stubGlobal('navigator', { share: vi.fn().mockRejectedValue(), clipboard: { writeText } });
46-
await shareLink({ classList: { add: vi.fn(), remove: vi.fn() } }, true, 'hash');
43+
await shareLink(true, 'hash');
4744
expect(writeText).toHaveBeenCalledWith('https://t.me/wishnibot?startgroup=hash');
4845
});
4946
});
5047

51-
it('should start animation', async () => {
52-
const add = vi.fn();
53-
vi.stubGlobal(
54-
'navigator',
55-
{ share: vi.fn().mockRejectedValue(), clipboard: { writeText: vi.fn() } },
56-
);
57-
await shareLink({ classList: { add, remove: vi.fn() } }, Math.random() > 0.5, 'hash');
58-
expect(add).toHaveBeenCalledWith('clicked', 'relative');
59-
});
60-
61-
it('should clean up', async () => {
62-
let classes;
63-
const add = vi.fn((...args) => classes = args);
64-
const remove = vi.fn();
48+
it('should show toast', async () => {
6549
vi.stubGlobal(
6650
'navigator',
6751
{ share: vi.fn().mockRejectedValue(), clipboard: { writeText: vi.fn() } },
6852
);
69-
await shareLink({ classList: { add, remove } }, Math.random() > 0.5, 'hash');
70-
await vi.runAllTimersAsync();
71-
expect(remove).toHaveBeenCalledWith(...classes);
53+
await shareLink(Math.random() > 0.5, 'hash');
54+
expect(vi.mocked(toast.success)).toHaveBeenCalledWith('Скопировано', { duration: 1000 });
7255
});
7356
});
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
1+
import { toast } from 'svoast';
2+
13
/**
24
* Формирование ссылки на список пользователя в диалоге с ботом или для групп, в которых есть бот.
35
* По возможности вызов меню "Поделиться", иначе копирование ссылки в буфер обмена и индикация
46
* в интерфейсе
57
* @function shareLink
6-
* @param {HTMLElement} currentTarget Цель события клика по кнопке получения ссылки
78
* @param {boolean} isLinkForGroups Признак необходимости формирования ссылки для групп
89
* @param {string} hash Хэш пользователя
910
* @returns {void}
1011
* @async
1112
*/
12-
export const shareLink = async (currentTarget, isLinkForGroups, hash) => {
13+
export const shareLink = async (isLinkForGroups, hash) => {
1314
const link = `https://t.me/wishnibot?start${isLinkForGroups ? 'group' : ''}=${hash}`;
1415

1516
try {
1617
await navigator.share({ url: link });
1718
} catch {
1819
await navigator.clipboard.writeText(link);
19-
currentTarget.classList.add('clicked', 'relative');
20-
setTimeout(() => currentTarget.classList.remove('clicked', 'relative'), 1000);
20+
toast.success('Скопировано', { duration: 1000 });
2121
}
2222
};
Lines changed: 4 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import { inject } from '@tmible/wishlist-common/dependency-injector';
22
import { emit } from '@tmible/wishlist-common/event-bus';
3-
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
4-
import { GetUserHash } from '$lib/user/events.js';
5-
import { LinkService } from '../../injection-tokens.js';
3+
import { describe, expect, it, vi } from 'vitest';
64
import { shareLink } from '../share-link.js';
75

86
vi.mock('@tmible/wishlist-common/dependency-injector');
@@ -13,33 +11,10 @@ vi.mock('../../injection-tokens.js', () => ({ LinkService: 'link service' }));
1311
const linkServiceMock = { shareLink: vi.fn() };
1412

1513
describe('wishlist / use cases / share link', () => {
16-
beforeEach(() => {
17-
vi.mocked(inject).mockReturnValueOnce(linkServiceMock);
18-
});
19-
20-
afterEach(() => {
21-
vi.clearAllMocks();
22-
});
23-
24-
it('should inject wishlist link service', async () => {
25-
await shareLink('current target', 'is link for groups');
26-
expect(vi.mocked(inject)).toHaveBeenCalledWith(vi.mocked(LinkService));
27-
});
28-
29-
it('should emit GetUserHash event', async () => {
30-
await shareLink('current target', 'is link for groups');
31-
expect(vi.mocked(emit)).toHaveBeenCalledWith(GetUserHash);
32-
});
33-
3414
it('should share link', async () => {
15+
vi.mocked(inject).mockReturnValueOnce(linkServiceMock);
3516
vi.mocked(emit).mockResolvedValueOnce('hash');
36-
await shareLink('current target', 'is link for groups');
37-
expect(
38-
linkServiceMock.shareLink,
39-
).toHaveBeenCalledWith(
40-
'current target',
41-
'is link for groups',
42-
'hash',
43-
);
17+
await shareLink('is link for groups');
18+
expect(linkServiceMock.shareLink).toHaveBeenCalledWith('is link for groups', 'hash');
4419
});
4520
});

portal/src/lib/wishlist/use-cases/share-link.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,10 @@ import { LinkService } from '../injection-tokens.js';
88
/**
99
* Формирование и отправка ссылки
1010
* @function shareLink
11-
* @param {HTMLElement} currentTarget HTML элемент для анимации успешного копирования ссылки
1211
* @param {boolean} isLinkForGroups Признак формирования ссылки для групп
1312
* @returns {Promise<void>}
1413
* @async
1514
*/
16-
export const shareLink = async (currentTarget, isLinkForGroups) => {
17-
await inject(LinkService).shareLink(currentTarget, isLinkForGroups, await emit(GetUserHash));
15+
export const shareLink = async (isLinkForGroups) => {
16+
await inject(LinkService).shareLink(isLinkForGroups, await emit(GetUserHash));
1817
};

0 commit comments

Comments
 (0)