ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m39s
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 1m2s
ci / ts / ts (packages + web) (push) Successful in 1m5s
ci / docker / docker (образы собираются — их сервер собирает сам при обновлении) (push) Successful in 39s
- expo-router app in src/app: connect (server check, recent servers), login, mandatory credential / password change, tabs Home / Search / Collection / Profile, album and artist pages, full-screen player - AuthSession per server with the refresh token in expo-secure-store (Android Keystore); language from the profile - player on react-native-track-player: ExoPlayer queue with a notification and lock-screen controls via a playback service, 500 MB stream cache, quality by network (Wi-Fi high, cellular medium), play events with played time, reactions, playback state restore and the endless My Wave with feedback - home: pulsing wave circle driven by BPM / energy in the cover palette, activity and mood chips that switch the wave on the fly - New Architecture is off until react-native-track-player supports it; the release build runs codegen only when it is on; query-string is a direct dependency because expo-router 5.1 imports it undeclared Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
22 lines
1.3 KiB
TypeScript
22 lines
1.3 KiB
TypeScript
import TrackPlayer, { Event } from 'react-native-track-player';
|
|
|
|
import { player } from './controller';
|
|
|
|
/**
|
|
* Фоновый сервис: кнопки уведомления, экрана блокировки и гарнитуры. Работает и без UI —
|
|
* команды уходят прямо в ExoPlayer, а учёт прослушиваний ведёт тот же контроллер.
|
|
*/
|
|
export async function PlaybackService(): Promise<void> {
|
|
TrackPlayer.addEventListener(Event.RemotePlay, () => void TrackPlayer.play());
|
|
TrackPlayer.addEventListener(Event.RemotePause, () => void TrackPlayer.pause());
|
|
TrackPlayer.addEventListener(Event.RemoteStop, () => void TrackPlayer.stop());
|
|
TrackPlayer.addEventListener(Event.RemoteNext, () => player.next());
|
|
TrackPlayer.addEventListener(Event.RemotePrevious, () => void player.prev());
|
|
TrackPlayer.addEventListener(Event.RemoteSeek, ({ position }) => player.seek(position * 1000));
|
|
// Звонок / голосовой ассистент: приостанавливаем и продолжаем сами (autoHandleInterruptions — для фокуса).
|
|
TrackPlayer.addEventListener(Event.RemoteDuck, ({ paused, permanent }) => {
|
|
if (permanent) void TrackPlayer.pause();
|
|
else if (paused) void TrackPlayer.pause();
|
|
});
|
|
}
|