feat(web): align the web UI with the design prototype
ci / api / api (push) Successful in 43s
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 52s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m36s
ci / ts / ts (packages + web) (push) Successful in 1m39s

- Ambient background in the app shell: three drifting blurred blobs,
  the third one tinted with the current track's cover; can be turned off
  in settings and stays still with reduced motion.
- Island player variant (floating glass panel) next to the bar, chosen
  in settings; player source line ("Album · …", "My Wave"), reactions
  around the transport controls, queue drawer.
- Sidebar: like / dislike counters, pending uploads badge on Queue,
  admin Settings page holding the upload queue limits.
- Collection: header tile with kicker, underline tabs, time / number
  lead column with an equalizer for the current track, album column,
  dimmed dislikes with undo, Play all / Shuffle pills.
- Album: cover-tinted header and Play / Shuffle; artist: artist wave,
  Play and popular tracks (new GET /artists/{id}/top-tracks).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mrleo1nidandClaude Opus 5.5 committed 2026-10-20 18:13:24 +03:00
1 parent 3afed02f23
commit 1c4e209e86
29 files changed
+1381 -339

No files matched your search

@@ -781,6 +781,25 @@ export interface paths {
patch?: never;
trace?: never;
};
"/api/v1/artists/{id}/top-tracks": {
parameters: {
query?: never;
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
/** Популярные треки исполнителя (по прослушиваниям всех пользователей) */
get: operations["listArtistTopTracks"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/v1/albums/{id}": {
parameters: {
query?: never;
@@ -3149,6 +3168,31 @@ export interface operations {
default: components["responses"]["Problem"];
};
};
listArtistTopTracks: {
parameters: {
query?: {
limit?: number;
};
header?: never;
path: {
id: components["parameters"]["EntityId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Треки, самые слушаемые первыми */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["TrackList"];
};
};
default: components["responses"]["Problem"];
};
};
getAlbum: {
parameters: {
query?: never;
+4
View File
@@ -327,5 +327,9 @@
"rejected": "Not accepted",
"error": "Error"
}
},
"server_settings": {
"title": "Server settings",
"subtitle": "Settings that apply to all users"
}
}
+32 -5
View File
@@ -33,7 +33,8 @@
"uploads": "Uploads",
"suggest": "Suggest tracks",
"my_uploads": "My uploads",
"upload_queue": "Upload queue"
"upload_queue": "Queue",
"admin_settings": "Settings"
},
"profile": {
"menu": "Profile menu",
@@ -70,7 +71,17 @@
"repeat_one": "Repeat track",
"progress": "Position",
"unavailable": "Track is unavailable — skipping",
"error": "Could not play the track"
"error": "Could not play the track",
"source_album": "Album · {{label}}",
"source_artist": "Artist · {{label}}",
"source_search": "Search · {{label}}",
"source_history": "History",
"source_likes": "Likes",
"source_dislikes": "Dislikes",
"source_wave": "My Wave",
"source_queue": "Queue",
"queue": "Queue",
"source_wave_seed": "Artist wave · {{label}}"
},
"settings": {
"title": "Settings",
@@ -96,7 +107,13 @@
"logout_all": "Sign out everywhere",
"wave_variant": "Wave style",
"wave_orb": "Orb",
"wave_liquid": "Liquid"
"wave_liquid": "Liquid",
"player_view": "Player style",
"player_bar": "Bar",
"player_island": "Island",
"ambient": "Ambient background",
"on": "On",
"off": "Off"
},
"form": {
"show_password": "Show password",
@@ -146,7 +163,10 @@
"col_duration": "Time",
"back_home": "Back home",
"artist": "Artist",
"album": "Album"
"album": "Album",
"play": "Play",
"artist_wave": "Artist wave",
"top_tracks": "Popular tracks"
},
"collection": {
"title": "Collection",
@@ -161,7 +181,14 @@
"empty_likes": "Tap the heart on tracks — they will gather here",
"empty_dislikes": "Disliked tracks stay out of the wave. None so far",
"play_all": "Play all",
"more": "Show more"
"more": "Show more",
"sub_history": "Everything you listened to, by day. Click a track to play it.",
"sub_likes_one": "{{count}} track · they shape My Wave the most",
"sub_likes_few": "{{count}} tracks · they shape My Wave the most",
"sub_likes_many": "{{count}} tracks · they shape My Wave the most",
"sub_likes_other": "{{count}} tracks · they shape My Wave the most",
"sub_dislikes": "These tracks never get into the wave or recommendations. Remove the dislike if you change your mind.",
"shuffle": "Shuffle"
},
"wave": {
"title": "My Wave",
+4
View File
@@ -327,5 +327,9 @@
"rejected": "Не принят",
"error": "Ошибка"
}
},
"server_settings": {
"title": "Настройки сервера",
"subtitle": "Параметры, которые действуют для всех пользователей"
}
}
+32 -5
View File
@@ -33,7 +33,8 @@
"uploads": "Предложения",
"suggest": "Предложить треки",
"my_uploads": "Мои предложения",
"upload_queue": "Очередь на добавление"
"upload_queue": "Очередь",
"admin_settings": "Настройки"
},
"profile": {
"menu": "Меню профиля",
@@ -70,7 +71,17 @@
"repeat_one": "Повторять трек",
"progress": "Позиция",
"unavailable": "Трек недоступен — пропускаем",
"error": "Не удалось воспроизвести трек"
"error": "Не удалось воспроизвести трек",
"source_album": "Альбом · {{label}}",
"source_artist": "Исполнитель · {{label}}",
"source_search": "Поиск · {{label}}",
"source_history": "История",
"source_likes": "Лайки",
"source_dislikes": "Дизлайки",
"source_wave": "Моя волна",
"source_queue": "Очередь",
"queue": "Очередь",
"source_wave_seed": "Волна по исполнителю · {{label}}"
},
"settings": {
"title": "Настройки",
@@ -96,7 +107,13 @@
"logout_all": "Выйти на всех устройствах",
"wave_variant": "Вид волны",
"wave_orb": "Сфера",
"wave_liquid": "Жидкая"
"wave_liquid": "Жидкая",
"player_view": "Вид плеера",
"player_bar": "Полоса",
"player_island": "Остров",
"ambient": "Живой фон",
"on": "Вкл.",
"off": "Выкл."
},
"form": {
"show_password": "Показать пароль",
@@ -146,7 +163,10 @@
"col_duration": "Время",
"back_home": "На главную",
"artist": "Исполнитель",
"album": "Альбом"
"album": "Альбом",
"play": "Слушать",
"artist_wave": "Волна по исполнителю",
"top_tracks": "Популярные треки"
},
"collection": {
"title": "Коллекция",
@@ -161,7 +181,14 @@
"empty_likes": "Отмечайте треки сердечком — они соберутся здесь",
"empty_dislikes": "Треки с дизлайком не попадут в волну. Пока таких нет",
"play_all": "Слушать всё",
"more": "Показать ещё"
"more": "Показать ещё",
"sub_history": "Всё, что вы слушали, по дням. Нажмите на трек, чтобы включить.",
"sub_likes_one": "{{count}} трек · влияют на «Мою волну» сильнее всего",
"sub_likes_few": "{{count}} трека · влияют на «Мою волну» сильнее всего",
"sub_likes_many": "{{count}} треков · влияют на «Мою волну» сильнее всего",
"sub_likes_other": "{{count}} трека · влияют на «Мою волну» сильнее всего",
"sub_dislikes": "Эти треки не попадают в волну и рекомендации. Снимите дизлайк, если передумали.",
"shuffle": "Перемешать"
},
"wave": {
"title": "Моя волна",