veza/apps/web/src/features/player
senke aeade50247 feat(ui): tooltip adoption + search highlighting & skeleton loading
Tooltip adoption (18 conversions across 11 files):
- Player controls: shuffle, repeat, mute, expand, close, lyrics, auto-scroll
- Navbar: theme toggle
- File browser: download, add tag, AI auto-tag, watermark, process with AI
- Notifications: mark as read
- Share links: open link, revoke link
- Chat: scroll to bottom

Search polish:
- New highlightMatch utility — wraps matching text in <mark> with primary color
- Applied to track titles, artist names, playlist names in SearchPageResults
- Applied to suggestion dropdown titles and subtitles
- Replaced spinner loading state with content-aware SearchPageSkeleton
- Skeleton matches actual results layout (tab bar, track cards, artist circles)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-09 23:14:00 +01:00
..
__tests__ refonte: backend-api go first; phase 1 2025-12-12 21:34:34 -05:00
components feat(ui): tooltip adoption + search highlighting & skeleton loading 2026-02-09 23:14:00 +01:00
hooks incus deployement fully implemented, Makefile updated and make fmt ran 2026-01-13 19:47:57 +01:00
services incus deployement fully implemented, Makefile updated and make fmt ran 2026-01-13 19:47:57 +01:00
store [FE-TYPE-011] fe-type: Add type safety for stores 2025-12-25 14:54:40 +01:00
index.ts refonte: backend-api go first; phase 1 2025-12-12 21:34:34 -05:00
README.md [INT-V2-003] Update documentation with id: string 2025-12-26 09:54:51 +01:00
types.test.ts refonte: backend-api go first; phase 1 2025-12-12 21:34:34 -05:00
types.ts ui(components): sidebar-aware player bar, synced lyrics, queue positioning 2026-02-08 22:48:08 +01:00

Player Feature

Vue d'ensemble

Le module Player fournit une solution complète de lecture audio pour l'application VEZA. Il inclut tous les composants nécessaires pour une expérience de lecture audio complète et moderne.

Architecture

Structure des fichiers

features/player/
├── components/          # Composants UI
│   ├── AudioPlayer.tsx          # Composant principal (intégration complète)
│   ├── MiniPlayer.tsx           # Version compacte du player
│   ├── TrackInfo.tsx            # Affichage des informations de la piste
│   ├── PlayPauseButton.tsx      # Bouton play/pause
│   ├── NextPreviousButtons.tsx  # Boutons next/previous
│   ├── ProgressBar.tsx          # Barre de progression
│   ├── TimeDisplay.tsx          # Affichage du temps
│   ├── VolumeControl.tsx        # Contrôle du volume
│   ├── RepeatShuffleButtons.tsx # Boutons repeat/shuffle
│   ├── QualitySelector.tsx      # Sélecteur de qualité
│   ├── PlaybackSpeedControl.tsx # Contrôle de vitesse
│   ├── PlayerError.tsx          # Affichage des erreurs
│   └── PlayerLoading.tsx        # État de chargement
├── hooks/               # Hooks React
│   ├── usePlayer.ts             # Hook principal
│   ├── useKeyboardShortcuts.ts  # Raccourcis clavier
│   └── useUsernameAvailability.ts # (auth feature)
├── store/               # State management
│   └── playerStore.ts           # Store Zustand
├── services/            # Services
│   └── playerService.ts         # Service audio
├── types.ts             # Types TypeScript
└── index.ts             # Exports publics

Utilisation

Composant principal AudioPlayer

import { AudioPlayer } from '@/features/player';

function MyComponent() {
  return (
    <AudioPlayer
      autoPlay={false}
      preload="metadata"
      showQualitySelector={true}
      showSpeedControl={true}
      compact={false}
    />
  );
}

Props du AudioPlayer

  • className?: string - Classes CSS personnalisées
  • autoPlay?: boolean - Lecture automatique (défaut: false)
  • preload?: 'none' | 'metadata' | 'auto' - Stratégie de préchargement (défaut: 'metadata')
  • showQualitySelector?: boolean - Afficher le sélecteur de qualité (défaut: true)
  • showSpeedControl?: boolean - Afficher le contrôle de vitesse (défaut: true)
  • compact?: boolean - Mode compact (défaut: false)

MiniPlayer

import { MiniPlayer } from '@/features/player';

function MyComponent() {
  const [isVisible, setIsVisible] = useState(false);

  return (
    <MiniPlayer
      isVisible={isVisible}
      onToggle={() => setIsVisible(false)}
      onClose={() => setIsVisible(false)}
      position="bottom"
    />
  );
}

Hook usePlayer

import { usePlayer } from '@/features/player';

function MyComponent() {
  const audioRef = useRef<HTMLAudioElement>(null);
  const player = usePlayer(audioRef);

  // Utiliser l'état et les contrôles
  const { currentTrack, isPlaying, play, pause } = player;

  return (
    <div>
      {currentTrack && <p>{currentTrack.title}</p>}
      <button onClick={isPlaying ? pause : () => play()}>
        {isPlaying ? 'Pause' : 'Play'}
      </button>
    </div>
  );
}

Raccourcis clavier

Les raccourcis clavier sont activés automatiquement dans AudioPlayer :

  • Espace : Play/Pause
  • Flèche gauche : Reculer de 5 secondes
  • Flèche droite : Avancer de 5 secondes
  • Flèche haut : Augmenter le volume
  • Flèche bas : Diminuer le volume

Composants individuels

TrackInfo

Affiche les informations de la piste (titre, artiste, cover, métadonnées).

import { TrackInfo } from '@/features/player';

<TrackInfo track={track} showCover={true} coverSize="md" showMetadata={true} />;

PlayPauseButton

Bouton pour contrôler la lecture/pause.

import { PlayPauseButton } from '@/features/player';

<PlayPauseButton
  isPlaying={isPlaying}
  onClick={handlePlayPause}
  size="md"
  variant="default"
/>;

ProgressBar

Barre de progression avec interaction drag et seek.

import { ProgressBar } from '@/features/player';

<ProgressBar
  currentTime={currentTime}
  duration={duration}
  onSeek={handleSeek}
  showTooltip={true}
/>;

VolumeControl

Contrôle du volume avec slider et bouton mute.

import { VolumeControl } from '@/features/player';

<VolumeControl
  volume={volume}
  muted={muted}
  onVolumeChange={setVolume}
  onMuteToggle={toggleMute}
  showValue={true}
  showSlider={true}
/>;

QualitySelector

Sélecteur de qualité audio.

import { QualitySelector } from '@/features/player';

<QualitySelector
  currentQuality="high"
  onQualityChange={setQuality}
  availableQualities={['auto', 'medium', 'high']}
/>;

PlaybackSpeedControl

Contrôle de la vitesse de lecture.

import { PlaybackSpeedControl } from '@/features/player';

<PlaybackSpeedControl
  currentSpeed={1}
  onSpeedChange={setSpeed}
  availableSpeeds={[0.5, 1, 1.5, 2]}
/>;

State Management

Le player utilise Zustand pour la gestion d'état globale. Le store est persistant (localStorage).

import { usePlayerStore } from '@/features/player';

const { currentTrack, isPlaying, volume, setVolume } = usePlayerStore();

Services

AudioPlayerService

Service pour gérer l'élément audio HTML directement.

import { audioPlayerService } from '@/features/player';

// Initialiser avec un élément audio
audioPlayerService.initialize(audioElement);

// Charger une piste
await audioPlayerService.loadTrack(track);

// Contrôles
await audioPlayerService.play();
audioPlayerService.pause();
audioPlayerService.seek(30); // 30 secondes
audioPlayerService.setVolume(0.5); // 50%

Types

Track

interface Track {
  id: string; // UUID from backend
  title: string;
  artist?: string;
  album?: string;
  duration: number;
  url: string;
  cover?: string;
  genre?: string;
}

PlayerState

interface PlayerState {
  currentTrack: Track | null;
  isPlaying: boolean;
  currentTime: number;
  duration: number;
  volume: number;
  muted: boolean;
  queue: Track[];
  currentIndex: number;
  repeat: 'off' | 'track' | 'playlist';
  shuffle: boolean;
}

Tests

Tous les composants incluent des tests unitaires avec une couverture ≥ 80%. Des tests end-to-end sont également disponibles dans __tests__/player.e2e.test.tsx.

Accessibilité

Tous les composants sont accessibles avec :

  • Support des lecteurs d'écran (ARIA labels)
  • Navigation au clavier
  • Focus visible
  • Rôles ARIA appropriés

Performance

  • Lazy loading des composants
  • Mémoization des callbacks
  • Optimisation des re-renders
  • Persistance intelligente du state

Compatibilité

  • Navigateurs modernes (Chrome, Firefox, Safari, Edge)
  • Support mobile (iOS, Android)
  • Dark mode
  • Responsive design