@djangocfg/ui-nextjs 2.1.82 → 2.1.83

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/package.json +4 -4
  2. package/src/tools/AudioPlayer/@refactoring3/00-IMPLEMENTATION-ROADMAP.md +1146 -0
  3. package/src/tools/AudioPlayer/@refactoring3/01-WAVESURFER-STREAMING-ANALYSIS.md +611 -0
  4. package/src/tools/AudioPlayer/@refactoring3/02-MEDIA-VIEWER-ANALYSIS.md +560 -0
  5. package/src/tools/AudioPlayer/@refactoring3/03-HYBRID-ARCHITECTURE-PROPOSAL.md +769 -0
  6. package/src/tools/AudioPlayer/@refactoring3/04-CRACKLING-ISSUE-DIAGNOSIS.md +373 -0
  7. package/src/tools/AudioPlayer/README.md +177 -205
  8. package/src/tools/AudioPlayer/components/AudioPlayer.tsx +9 -4
  9. package/src/tools/AudioPlayer/components/HybridAudioPlayer.tsx +251 -0
  10. package/src/tools/AudioPlayer/components/HybridSimplePlayer.tsx +291 -0
  11. package/src/tools/AudioPlayer/components/HybridWaveform.tsx +279 -0
  12. package/src/tools/AudioPlayer/components/SimpleAudioPlayer.tsx +16 -26
  13. package/src/tools/AudioPlayer/components/index.ts +6 -1
  14. package/src/tools/AudioPlayer/context/AudioProvider.tsx +8 -3
  15. package/src/tools/AudioPlayer/context/HybridAudioProvider.tsx +121 -0
  16. package/src/tools/AudioPlayer/context/index.ts +14 -2
  17. package/src/tools/AudioPlayer/hooks/index.ts +11 -0
  18. package/src/tools/AudioPlayer/hooks/useHybridAudio.ts +387 -0
  19. package/src/tools/AudioPlayer/hooks/useHybridAudioAnalysis.ts +95 -0
  20. package/src/tools/AudioPlayer/hooks/useSharedWebAudio.ts +6 -3
  21. package/src/tools/AudioPlayer/index.ts +31 -0
  22. package/src/tools/AudioPlayer/progressive/ProgressiveAudioPlayer.tsx +8 -0
  23. package/src/tools/index.ts +22 -0
  24. package/src/tools/AudioPlayer/@refactoring/00-PLAN.md +0 -148
  25. package/src/tools/AudioPlayer/@refactoring/01-TYPES.md +0 -301
  26. package/src/tools/AudioPlayer/@refactoring/02-HOOKS.md +0 -281
  27. package/src/tools/AudioPlayer/@refactoring/03-CONTEXT.md +0 -328
  28. package/src/tools/AudioPlayer/@refactoring/04-COMPONENTS.md +0 -251
  29. package/src/tools/AudioPlayer/@refactoring/05-EFFECTS.md +0 -427
  30. package/src/tools/AudioPlayer/@refactoring/06-UTILS-AND-INDEX.md +0 -193
  31. package/src/tools/AudioPlayer/@refactoring/07-EXECUTION-CHECKLIST.md +0 -146
  32. package/src/tools/AudioPlayer/@refactoring2/ISSUE_ANALYSIS.md +0 -187
  33. package/src/tools/AudioPlayer/@refactoring2/PLAN.md +0 -372
@@ -1,193 +0,0 @@
1
- # Phase 7-8: Utils and Main Index
2
-
3
- ## `utils/formatTime.ts`
4
-
5
- Extract from `AudioPlayer.tsx`.
6
-
7
- ```typescript
8
- /**
9
- * Format seconds to mm:ss display format.
10
- */
11
- export function formatTime(seconds: number): string {
12
- if (!seconds || !isFinite(seconds) || seconds < 0) return '0:00';
13
- const mins = Math.floor(seconds / 60);
14
- const secs = Math.floor(seconds % 60);
15
- return `${mins}:${secs.toString().padStart(2, '0')}`;
16
- }
17
- ```
18
-
19
- ---
20
-
21
- ## `utils/index.ts`
22
-
23
- ```typescript
24
- export { formatTime } from './formatTime';
25
- ```
26
-
27
- ---
28
-
29
- ## Main `index.ts` (Final Public API)
30
-
31
- ```typescript
32
- /**
33
- * AudioPlayer - Audio playback with waveform visualization
34
- *
35
- * Built on WaveSurfer.js with audio-reactive effects
36
- */
37
-
38
- // =============================================================================
39
- // COMPONENTS
40
- // =============================================================================
41
-
42
- // Simple wrapper (recommended)
43
- export { SimpleAudioPlayer } from './components';
44
- export type { SimpleAudioPlayerProps } from './components';
45
-
46
- // Core components
47
- export { AudioPlayer } from './components';
48
- export { AudioEqualizer } from './components';
49
- export { AudioReactiveCover } from './components';
50
- export { AudioShortcutsPopover } from './components';
51
- export { VisualizationToggle } from './components';
52
-
53
- // =============================================================================
54
- // CONTEXT & HOOKS
55
- // =============================================================================
56
-
57
- // Provider and hooks
58
- export {
59
- AudioProvider,
60
- useAudio,
61
- useAudioControls,
62
- useAudioState,
63
- useAudioElement,
64
- } from './context';
65
-
66
- // Hotkeys
67
- export { useAudioHotkeys, AUDIO_SHORTCUTS } from './hooks';
68
-
69
- // Visualization settings
70
- export {
71
- useAudioVisualization,
72
- VisualizationProvider,
73
- VARIANT_INFO,
74
- INTENSITY_INFO,
75
- COLOR_SCHEME_INFO,
76
- } from './hooks';
77
-
78
- // =============================================================================
79
- // EFFECTS
80
- // =============================================================================
81
-
82
- export {
83
- INTENSITY_CONFIG,
84
- COLOR_SCHEMES,
85
- getEffectConfig,
86
- getColors,
87
- prepareEffectColors,
88
- calculateGlowLayers,
89
- calculateOrbs,
90
- calculateMeshGradients,
91
- calculateSpotlight,
92
- EFFECT_ANIMATIONS,
93
- } from './effects';
94
-
95
- // =============================================================================
96
- // TYPES
97
- // =============================================================================
98
-
99
- export type {
100
- // Audio types
101
- AudioSource,
102
- PlaybackStatus,
103
- WaveformOptions,
104
- EqualizerOptions,
105
- SharedWebAudioContext,
106
- AudioContextState,
107
- // Component props
108
- AudioPlayerProps,
109
- AudioEqualizerProps,
110
- AudioReactiveCoverProps,
111
- AudioViewerProps,
112
- // Effect types
113
- EffectVariant,
114
- EffectIntensity,
115
- EffectColorScheme,
116
- AudioLevels,
117
- EffectConfig,
118
- EffectColors,
119
- EffectLayer,
120
- } from './types';
121
-
122
- // Visualization types
123
- export type {
124
- VisualizationSettings,
125
- VisualizationVariant,
126
- VisualizationIntensity,
127
- VisualizationColorScheme,
128
- UseAudioVisualizationReturn,
129
- VisualizationProviderProps,
130
- } from './hooks';
131
-
132
- // Hotkey types
133
- export type {
134
- AudioHotkeyOptions,
135
- ShortcutItem,
136
- ShortcutGroup,
137
- } from './hooks';
138
- ```
139
-
140
- ---
141
-
142
- ## Folder Structure Summary
143
-
144
- After refactoring:
145
-
146
- ```
147
- AudioPlayer/
148
- ├── index.ts # ~80 lines (exports only)
149
-
150
- ├── types/
151
- │ ├── index.ts # ~30 lines
152
- │ ├── audio.ts # ~80 lines
153
- │ ├── components.ts # ~50 lines
154
- │ └── effects.ts # ~60 lines
155
-
156
- ├── hooks/
157
- │ ├── index.ts # ~30 lines
158
- │ ├── useSharedWebAudio.ts # ~90 lines
159
- │ ├── useAudioAnalysis.ts # ~100 lines
160
- │ ├── useAudioHotkeys.ts # ~150 lines
161
- │ └── useVisualization.tsx # ~200 lines
162
-
163
- ├── context/
164
- │ ├── index.ts # ~5 lines
165
- │ ├── AudioProvider.tsx # ~180 lines
166
- │ └── selectors.ts # ~60 lines
167
-
168
- ├── components/
169
- │ ├── index.ts # ~15 lines
170
- │ ├── AudioPlayer.tsx # ~200 lines
171
- │ ├── AudioEqualizer.tsx # ~200 lines
172
- │ ├── SimpleAudioPlayer.tsx # ~280 lines
173
- │ ├── ShortcutsPopover.tsx # ~95 lines
174
- │ ├── VisualizationToggle.tsx # ~70 lines
175
- │ └── ReactiveCover/
176
- │ ├── index.tsx # ~100 lines
177
- │ ├── GlowEffect.tsx # ~80 lines
178
- │ ├── OrbsEffect.tsx # ~40 lines
179
- │ ├── SpotlightEffect.tsx # ~60 lines
180
- │ └── MeshEffect.tsx # ~50 lines
181
-
182
- ├── effects/
183
- │ ├── index.ts # ~20 lines
184
- │ ├── constants.ts # ~50 lines
185
- │ ├── calculations.ts # ~250 lines
186
- │ └── animations.ts # ~80 lines
187
-
188
- └── utils/
189
- ├── index.ts # ~3 lines
190
- └── formatTime.ts # ~10 lines
191
-
192
- Total: ~23 files, avg ~85 lines per file (vs current 12 files, avg ~240 lines)
193
- ```
@@ -1,146 +0,0 @@
1
- # Execution Checklist
2
-
3
- ## Pre-flight
4
-
5
- - [ ] Run `pnpm check` - ensure current code compiles
6
- - [ ] Commit current state as backup
7
-
8
- ---
9
-
10
- ## Phase 1: Create Folder Structure
11
-
12
- ```bash
13
- cd src/tools/AudioPlayer
14
- mkdir -p types hooks context components/ReactiveCover effects utils
15
- ```
16
-
17
- - [ ] Create `types/` folder
18
- - [ ] Create `hooks/` folder
19
- - [ ] Create `context/` folder
20
- - [ ] Create `components/` folder
21
- - [ ] Create `components/ReactiveCover/` folder
22
- - [ ] Create `effects/` subfolder (already exists, will add files)
23
- - [ ] Create `utils/` folder
24
-
25
- ---
26
-
27
- ## Phase 2: Types Split
28
-
29
- - [ ] Create `types/audio.ts`
30
- - [ ] Create `types/components.ts`
31
- - [ ] Create `types/effects.ts`
32
- - [ ] Create `types/index.ts`
33
- - [ ] Run `pnpm check`
34
-
35
- ---
36
-
37
- ## Phase 3: Hooks Extraction
38
-
39
- - [ ] Create `hooks/useSharedWebAudio.ts` (extract from context.tsx)
40
- - [ ] Create `hooks/useAudioAnalysis.ts` (extract from context.tsx)
41
- - [ ] Move `useAudioHotkeys.ts` → `hooks/useAudioHotkeys.ts`
42
- - [ ] Move `useAudioVisualization.tsx` → `hooks/useVisualization.tsx`
43
- - [ ] Create `hooks/index.ts`
44
- - [ ] Run `pnpm check`
45
-
46
- ---
47
-
48
- ## Phase 4: Context Refactoring
49
-
50
- - [ ] Create `context/AudioProvider.tsx`
51
- - [ ] Create `context/selectors.ts`
52
- - [ ] Create `context/index.ts`
53
- - [ ] Delete old `context.tsx`
54
- - [ ] Run `pnpm check`
55
-
56
- ---
57
-
58
- ## Phase 5: Components Reorganization
59
-
60
- - [ ] Move `AudioPlayer.tsx` → `components/AudioPlayer.tsx`
61
- - [ ] Move `AudioEqualizer.tsx` → `components/AudioEqualizer.tsx`
62
- - [ ] Move `SimpleAudioPlayer.tsx` → `components/SimpleAudioPlayer.tsx`
63
- - [ ] Move `AudioShortcutsPopover.tsx` → `components/ShortcutsPopover.tsx`
64
- - [ ] Move `VisualizationToggle.tsx` → `components/VisualizationToggle.tsx`
65
- - [ ] Split `AudioReactiveCover.tsx` into `components/ReactiveCover/`
66
- - [ ] Create `components/ReactiveCover/index.tsx`
67
- - [ ] Create `components/ReactiveCover/GlowEffect.tsx`
68
- - [ ] Create `components/ReactiveCover/OrbsEffect.tsx`
69
- - [ ] Create `components/ReactiveCover/SpotlightEffect.tsx`
70
- - [ ] Create `components/ReactiveCover/MeshEffect.tsx`
71
- - [ ] Create `components/index.ts`
72
- - [ ] Delete old component files from root
73
- - [ ] Run `pnpm check`
74
-
75
- ---
76
-
77
- ## Phase 6: Effects Refactoring
78
-
79
- - [ ] Create `effects/constants.ts`
80
- - [ ] Create `effects/calculations.ts`
81
- - [ ] Create `effects/animations.ts`
82
- - [ ] Update `effects/index.ts`
83
- - [ ] Run `pnpm check`
84
-
85
- ---
86
-
87
- ## Phase 7: Utils
88
-
89
- - [ ] Create `utils/formatTime.ts`
90
- - [ ] Create `utils/index.ts`
91
- - [ ] Run `pnpm check`
92
-
93
- ---
94
-
95
- ## Phase 8: Update Main Index
96
-
97
- - [ ] Rewrite `index.ts` with new import paths
98
- - [ ] Run `pnpm check`
99
-
100
- ---
101
-
102
- ## Phase 9: Cleanup & Verification
103
-
104
- - [ ] Delete old files:
105
- - [ ] `context.tsx`
106
- - [ ] `types.ts`
107
- - [ ] `useAudioHotkeys.ts` (moved)
108
- - [ ] `useAudioVisualization.tsx` (moved)
109
- - [ ] `AudioPlayer.tsx` (moved)
110
- - [ ] `AudioEqualizer.tsx` (moved)
111
- - [ ] `SimpleAudioPlayer.tsx` (moved)
112
- - [ ] `AudioShortcutsPopover.tsx` (moved)
113
- - [ ] `VisualizationToggle.tsx` (moved)
114
- - [ ] `AudioReactiveCover.tsx` (split)
115
-
116
- - [ ] Run `pnpm check` - final verification
117
- - [ ] Test in playground
118
- - [ ] Commit refactoring
119
-
120
- ---
121
-
122
- ## Rollback Plan
123
-
124
- If something goes wrong:
125
-
126
- ```bash
127
- git checkout HEAD -- src/tools/AudioPlayer/
128
- ```
129
-
130
- ---
131
-
132
- ## Files to Delete (after successful migration)
133
-
134
- ```
135
- src/tools/AudioPlayer/
136
- ├── context.tsx # → context/AudioProvider.tsx + context/selectors.ts
137
- ├── types.ts # → types/*.ts
138
- ├── useAudioHotkeys.ts # → hooks/useAudioHotkeys.ts
139
- ├── useAudioVisualization.tsx # → hooks/useVisualization.tsx
140
- ├── AudioPlayer.tsx # → components/AudioPlayer.tsx
141
- ├── AudioEqualizer.tsx # → components/AudioEqualizer.tsx
142
- ├── SimpleAudioPlayer.tsx # → components/SimpleAudioPlayer.tsx
143
- ├── AudioShortcutsPopover.tsx # → components/ShortcutsPopover.tsx
144
- ├── VisualizationToggle.tsx # → components/VisualizationToggle.tsx
145
- └── AudioReactiveCover.tsx # → components/ReactiveCover/*.tsx
146
- ```
@@ -1,187 +0,0 @@
1
- # Audio Player Seek Issue Analysis
2
-
3
- **Date:** 2025-12-27
4
- **Issue:** При seek на позицию > 2 минут аудио перестаёт воспроизводиться
5
-
6
- ## Симптомы
7
-
8
- 1. Трек начинает проигрываться нормально
9
- 2. Seek на позицию < 2 минут работает
10
- 3. Seek на позицию > 2 минут - воспроизведение останавливается
11
- 4. После seek > 2 минут, возврат на < 2 минут тоже не работает
12
-
13
- ## Корневая причина
14
-
15
- ### Проблема в архитектуре streaming + WaveSurfer
16
-
17
- **WaveSurfer.js** по умолчанию загружает **весь аудиофайл** в память перед воспроизведением. Но в текущей реализации используется **HTTP Range streaming**, который возвращает данные **по частям**.
18
-
19
- #### Ключевые константы (Django backend):
20
-
21
- ```python
22
- # viewsets.py
23
- DEFAULT_CHUNK_SIZE = 2 * 1024 * 1024 # 2 MB
24
- MAX_CHUNK_SIZE = 10 * 1024 * 1024 # 10 MB
25
- ```
26
-
27
- #### Что происходит:
28
-
29
- 1. **Загрузка аудио:**
30
- - WaveSurfer запрашивает URL: `/api/terminal/media-stream/{session_id}/stream/?path=...`
31
- - Backend возвращает **только первые 2 MB** (DEFAULT_CHUNK_SIZE)
32
- - WaveSurfer декодирует эти 2 MB и считает файл "готовым"
33
-
34
- 2. **При seek на < 2 минут:**
35
- - Данные уже в буфере (первые 2 MB)
36
- - Seek работает
37
-
38
- 3. **При seek на > 2 минут:**
39
- - Данные НЕ загружены (за пределами первых 2 MB)
40
- - WaveSurfer пытается seek в "пустоту"
41
- - HTML5 Audio element не может воспроизвести незагруженные данные
42
- - Плеер "зависает"
43
-
44
- 4. **После неудачного seek:**
45
- - Состояние плеера повреждено
46
- - Даже возврат на загруженную часть не работает
47
-
48
- ### Почему именно 2 минуты?
49
-
50
- MP3 128kbps ≈ 16 KB/сек
51
- 2 MB / 16 KB = **125 секунд ≈ 2 минуты**
52
-
53
- Для других битрейтов:
54
- - 192kbps: ~87 секунд
55
- - 256kbps: ~65 секунд
56
- - 320kbps: ~52 секунды
57
-
58
- ## Решения
59
-
60
- ### Вариант 1: Полная загрузка файла (Рекомендуется для небольших файлов)
61
-
62
- **Изменить AudioViewer.tsx:**
63
-
64
- ```typescript
65
- // Вместо streaming для аудио < 50MB, загружать полностью
66
- const shouldFullLoad = file.size < 50 * 1024 * 1024 && isAudio;
67
-
68
- if (shouldFullLoad) {
69
- // Загрузить через RPC или fetch весь файл
70
- const response = await fetch(streamUrl);
71
- const blob = await response.blob();
72
- const blobUrl = URL.createObjectURL(blob);
73
- setSrc(blobUrl);
74
- } else {
75
- // Streaming для больших файлов
76
- setSrc(streamUrl);
77
- }
78
- ```
79
-
80
- ### Вариант 2: Использовать Media Source Extensions (MSE)
81
-
82
- WaveSurfer поддерживает MSE для progressive loading:
83
-
84
- ```typescript
85
- // AudioProvider.tsx
86
- const options = useMemo(() => ({
87
- container: containerRef,
88
- url: source.uri,
89
- // Включить backend режим для streaming
90
- backend: 'MediaElement',
91
- mediaControls: false,
92
- // ...
93
- }), [...]);
94
- ```
95
-
96
- **Требует изменений в backend** для правильной обработки Range requests.
97
-
98
- ### Вариант 3: Исправить backend Range handling
99
-
100
- **Django viewsets.py** - убрать ограничение chunk size для аудио:
101
-
102
- ```python
103
- def stream(self, request, session_id: str):
104
- # Для аудио - возвращать весь файл или больший chunk
105
- if mime_type.startswith('audio/') and file_size < 100 * 1024 * 1024:
106
- # Возвращать весь файл для аудио < 100MB
107
- chunk_size = file_size
108
- else:
109
- chunk_size = min(requested_length or DEFAULT_CHUNK_SIZE, MAX_CHUNK_SIZE)
110
- ```
111
-
112
- ### Вариант 4: Использовать HTML5 Audio напрямую (без WaveSurfer waveform)
113
-
114
- Для streaming источников отключить waveform rendering:
115
-
116
- ```typescript
117
- <SimpleAudioPlayer
118
- src={streamUrl}
119
- showWaveform={false} // Отключить waveform для streaming
120
- // ...
121
- />
122
- ```
123
-
124
- HTML5 `<audio>` элемент сам обрабатывает Range requests корректно.
125
-
126
- ## Быстрое временное решение
127
-
128
- В `AudioViewer.tsx` изменить условие для использования blob вместо streaming для аудио:
129
-
130
- ```typescript
131
- // Текущий код:
132
- const shouldStream = (file.loadMethod === 'http_stream' || file.loadMethod === 'http_transcode')
133
- && !hasContent && sessionId;
134
-
135
- // Изменить на:
136
- const isAudio = file.mimeType?.startsWith('audio/');
137
- const shouldStream = !isAudio && (file.loadMethod === 'http_stream' || file.loadMethod === 'http_transcode')
138
- && !hasContent && sessionId;
139
-
140
- // Для аудио - загружать через fetch
141
- if (isAudio && sessionId && !hasContent) {
142
- const fetchAudio = async () => {
143
- const url = getStreamUrlWithTranscode(sessionId, file.path, needsTranscode);
144
- const response = await fetch(url);
145
- const blob = await response.blob();
146
- setSrc(URL.createObjectURL(blob));
147
- };
148
- fetchAudio();
149
- }
150
- ```
151
-
152
- ## Дополнительные находки
153
-
154
- ### Баг в useAudioHotkeys.ts (исправлен)
155
-
156
- В `/projects/solution/frontend/packages/ui-nextjs/src/tools/AudioPlayer/hooks/useAudioHotkeys.ts` был баг:
157
-
158
- ```typescript
159
- // Было (НЕПРАВИЛЬНО):
160
- skip(duration * percent - duration * (volume || 0));
161
-
162
- // Стало (ПРАВИЛЬНО):
163
- const targetTime = duration * percent;
164
- skip(targetTime - currentTime);
165
- ```
166
-
167
- Использовался `volume` (громкость) вместо `currentTime` для расчёта seek позиции.
168
-
169
- ## Файлы для изменения
170
-
171
- 1. **Frontend:**
172
- - `cmdop/projects/solution/frontend/apps/web/app/_layouts/FileWorkspace/viewers/media/AudioViewer.tsx`
173
-
174
- 2. **Backend (опционально):**
175
- - `cmdop/projects/solution/django/apps/terminal/views/api/media_stream/viewsets.py`
176
-
177
- 3. **UI Library (уже исправлено):**
178
- - `djangocfg/projects/solution/frontend/packages/ui-nextjs/src/tools/AudioPlayer/hooks/useAudioHotkeys.ts`
179
-
180
- ## Архитектурная рекомендация
181
-
182
- Для аудиофайлов рекомендуется:
183
- - **< 50 MB**: Полная загрузка в blob (лучший UX, работает seek)
184
- - **50-200 MB**: HTML5 Audio без waveform (streaming, но без визуализации)
185
- - **> 200 MB**: Показать предупреждение, предложить скачать
186
-
187
- WaveSurfer waveform visualization требует полной загрузки файла для корректной работы.