Skip to content

Commit bbbac10

Browse files
chatman-mediaclaude
andcommitted
feat(browser): добавлена кнопка "Очистить всё" для медиафайлов
Изменения: - Добавлена кнопка "Clear All" на вкладке Media - Диалог подтверждения с количеством файлов - Обработчик handleClearAllMedia для удаления всех медиафайлов - Переводы в en.json и ru.json для clearAll и clearAllConfirm - Обновлены типы media-management для removeMultipleMedia Дополнительные изменения: - Исправлены тесты AI Director (PascalCase mode values) - Улучшен mock AIDirectorService с полным AIDirectorConfig - Добавлены stream URL функции в video preview компонентах 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent bef116f commit bbbac10

File tree

15 files changed

+185
-43
lines changed

15 files changed

+185
-43
lines changed

src/adapters/tauri/ai.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -556,9 +556,11 @@ export class TauriAIService implements IAIService {
556556
return invoke("ai_director_get_capabilities")
557557
}
558558

559-
async aiDirectorGetDefaultConfig(mode: "fast" | "balanced" | "quality" | "custom"): Promise<AIDirectorConfig> {
559+
async aiDirectorGetDefaultConfig(mode: "Fast" | "Balanced" | "Quality" | "Custom"): Promise<AIDirectorConfig> {
560560
logger.debugSync("Getting default config", { mode })
561-
return invoke("ai_director_get_default_config", { mode })
561+
// Конвертируем в lowercase для Rust команды (если нужно)
562+
const rustMode = mode.toLowerCase() as "fast" | "balanced" | "quality" | "custom"
563+
return invoke("ai_director_get_default_config", { mode: rustMode })
562564
}
563565

564566
async aiDirectorValidateConfig(config: AIDirectorConfig): Promise<ConfigValidationResult> {
@@ -581,7 +583,7 @@ export class TauriAIService implements IAIService {
581583
enable_ffmpeg_analysis?: boolean
582584
enable_montage_analysis?: boolean
583585
enable_transcription?: boolean
584-
performance_mode?: "fast" | "balanced" | "quality"
586+
performance_mode?: "Fast" | "Balanced" | "Quality"
585587
},
586588
): Promise<unknown> {
587589
logger.infoSync("Running unified audio comprehensive analysis", { videoPath })
@@ -591,7 +593,7 @@ export class TauriAIService implements IAIService {
591593
enable_ffmpeg_analysis: config?.enable_ffmpeg_analysis ?? true,
592594
enable_montage_analysis: config?.enable_montage_analysis ?? true,
593595
enable_transcription: config?.enable_transcription ?? false,
594-
performance_mode: config?.performance_mode ?? "balanced",
596+
performance_mode: config?.performance_mode ?? "Balanced",
595597
},
596598
})
597599
}
@@ -603,12 +605,12 @@ export class TauriAIService implements IAIService {
603605

604606
async unifiedAudioAnalyzeBatch(
605607
filePaths: string[],
606-
config?: { performance_mode?: "fast" | "balanced" | "quality" },
608+
config?: { performance_mode?: "Fast" | "Balanced" | "Quality" },
607609
): Promise<unknown[]> {
608610
logger.infoSync("Running unified audio batch analysis", { fileCount: filePaths.length })
609611
return invoke("unified_audio_analyze_batch", {
610612
filePaths,
611-
config: { performance_mode: config?.performance_mode ?? "fast" },
613+
config: { performance_mode: config?.performance_mode ?? "Fast" },
612614
})
613615
}
614616

src/domains/ai-director/tauri/__tests__/ai-director-commands.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ describe("AI Director Tauri Commands", () => {
334334
enable_object_detection: true,
335335
enable_face_recognition: true,
336336
enable_transcription: true,
337-
max_memory_mb: 100, // Very low
337+
max_parallel_files: 100, // Very low
338338
}
339339

340340
const mockValidation: ConfigValidationResult = {

src/domains/ai-services/__mocks__/ai-director-service.ts

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,15 +88,40 @@ export const mockSystemStatus: SystemStatus = {
8888
}
8989

9090
export const mockAIDirectorConfig: AIDirectorConfig = {
91-
performance_mode: "Balanced", // PascalCase
91+
performance_mode: "Balanced",
9292
enable_audio_analysis: true,
9393
enable_scene_detection: true,
9494
enable_video_analysis: true,
95+
enable_vision_analysis: true,
96+
enable_face_detection: false,
97+
enable_face_analysis: false,
9598
enable_object_detection: false,
96-
enable_face_recognition: false,
97-
enable_transcription: true,
98-
timeout_seconds: 60,
99-
max_memory_mb: 1024,
99+
enable_object_analysis: false,
100+
enable_emotion_analysis: false,
101+
enable_moment_detection: true,
102+
enable_content_classification: true,
103+
enable_composition_analysis: false,
104+
enable_mood_analysis: false,
105+
enable_quality_analysis: true,
106+
max_processing_time: 60,
107+
quality_threshold: 50,
108+
max_key_moments: 50,
109+
enable_caching: true,
110+
generate_editing_recommendations: false,
111+
enable_mcp_agents: false,
112+
ai_provider: null,
113+
ai_model: null,
114+
ai_api_key: null,
115+
enable_ai_enhanced_analysis: false,
116+
enable_ai_descriptions: false,
117+
enable_ai_mood_analysis: false,
118+
enable_vision_language_model: false,
119+
vlm_model: null,
120+
vlm_num_frames: 5,
121+
vlm_temperature: 0.7,
122+
vlm_max_tokens: 500,
123+
enable_parallel_processing: false,
124+
max_parallel_files: null,
100125
}
101126

102127
export const aiDirectorService = {

src/domains/ai-services/machines/__tests__/ai-intelligence-machine.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ describe("AI Intelligence Machine", () => {
110110
const config: Partial<AIDirectorConfig> = {
111111
enable_audio_analysis: true,
112112
enable_scene_detection: true,
113-
timeout_seconds: 120,
113+
max_processing_time: 120,
114114
}
115115

116116
actor.send({

src/domains/ai-services/services/__tests__/unified-orchestrator.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ describe("UnifiedOrchestrator", () => {
314314
enable_audio_analysis: true,
315315
enable_scene_detection: false,
316316
enable_video_analysis: true,
317-
timeout_seconds: 30,
317+
max_processing_time: 30,
318318
}
319319

320320
await orchestrator.analyzeComprehensive("/test/video.mp4", {

src/domains/media-management/index.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,9 @@ export type {
118118
BrowserVideoMetadata,
119119
FileOperationsContext,
120120
FileOperationsEvent,
121+
FileStatus,
121122
// Core media types
122123
FileGroup,
123-
FfprobeChapter,
124124
FfprobeData,
125125
FfprobeFormat,
126126
FfprobeStream,
@@ -139,15 +139,13 @@ export type {
139139
MediaManagementService,
140140
MediaMetadata,
141141
MediaPool,
142-
MediaPoolFilter,
143142
MediaPoolItem,
144-
MediaPoolSort,
145-
MediaPoolView,
146143
MediaPreviewData,
147-
PreviewGenerationOptions,
144+
MediaTrack,
145+
MusicMetadata,
148146
QualityMetrics,
147+
RecognitionResults,
149148
SavedMediaFile,
150-
SavedMediaMetadata,
151149
SavedMusicFile,
152150
SceneDetectionResult,
153151
ThumbnailData,

src/domains/media-management/types/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
export type {
1313
FileGroup,
1414
MediaFile,
15+
MediaTrack,
1516
VideoSegment,
1617
} from "./media"
1718
export { MediaType } from "./media"

src/features/browser/components/browser-content.tsx

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,24 @@
11
import { memo, useCallback, useEffect, useState } from "react"
2+
import { useTranslation } from "react-i18next"
23

34
import { useBrowserState } from "@/domains/browser"
45
import { useMediaManagement } from "@/domains/media-management"
56
import { useMusicImport } from "@/features/browser/hooks/use-music-import"
67
import { DeveloperToolsButton, DeveloperToolsModal } from "@/features/developer-tools"
78
import { useMediaImport } from "@/domains/media-management"
9+
import { Trash2 } from "lucide-react"
10+
import {
11+
AlertDialog,
12+
AlertDialogAction,
13+
AlertDialogCancel,
14+
AlertDialogContent,
15+
AlertDialogDescription,
16+
AlertDialogFooter,
17+
AlertDialogHeader,
18+
AlertDialogTitle,
19+
AlertDialogTrigger,
20+
} from "@/components/ui/alert-dialog"
21+
import { Button } from "@/components/ui/button"
822

923
import { BrowserLoadingIndicator } from "./browser-loading-indicator"
1024
import { BrowserToolbarWrapper } from "./browser-toolbar-wrapper"
@@ -28,6 +42,8 @@ TabContentContainer.displayName = "TabContentContainer"
2842
* Поддерживает все типы контента через единую архитектуру
2943
*/
3044
export const BrowserContent = memo(() => {
45+
const { t } = useTranslation()
46+
3147
// Developer Tools модалка
3248
const [showDeveloperTools, setShowDeveloperTools] = useState(false)
3349

@@ -76,6 +92,15 @@ export const BrowserContent = memo(() => {
7692
isImporting: isImportingMusic,
7793
} = useMusicImport()
7894

95+
// Обработчик очистки всех медиафайлов
96+
const handleClearAllMedia = useCallback(async () => {
97+
if (mediaPool.size === 0) return
98+
99+
const allMediaIds = Array.from(mediaPool.keys())
100+
await removeMultipleMedia(allMediaIds)
101+
await deselectAllFiles()
102+
}, [mediaPool, removeMultipleMedia, deselectAllFiles])
103+
79104
// Keyboard shortcuts для Browser
80105
useEffect(() => {
81106
const handleKeyDown = (event: KeyboardEvent) => {
@@ -140,9 +165,32 @@ export const BrowserContent = memo(() => {
140165
setPreviewSize(previewSizeIndex - 1)
141166
}, [previewSizeIndex, setPreviewSize])
142167

143-
// Дополнительные кнопки для вкладки Effects
168+
// Дополнительные кнопки для разных вкладок
144169
const extraButtons =
145-
activeTab === "effects" ? <DeveloperToolsButton onClick={() => setShowDeveloperTools(true)} /> : undefined
170+
activeTab === "effects" ? (
171+
<DeveloperToolsButton onClick={() => setShowDeveloperTools(true)} />
172+
) : activeTab === "media" && mediaPool.size > 0 ? (
173+
<AlertDialog>
174+
<AlertDialogTrigger asChild>
175+
<Button variant="ghost" size="sm" className="h-8 gap-2">
176+
<Trash2 className="h-4 w-4" />
177+
{t("browser.clearAll")}
178+
</Button>
179+
</AlertDialogTrigger>
180+
<AlertDialogContent>
181+
<AlertDialogHeader>
182+
<AlertDialogTitle>{t("browser.clearAllConfirm.title")}</AlertDialogTitle>
183+
<AlertDialogDescription>
184+
{t("browser.clearAllConfirm.description")} ({mediaPool.size} {t("common.files", { count: mediaPool.size })})
185+
</AlertDialogDescription>
186+
</AlertDialogHeader>
187+
<AlertDialogFooter>
188+
<AlertDialogCancel>{t("browser.clearAllConfirm.cancel")}</AlertDialogCancel>
189+
<AlertDialogAction onClick={handleClearAllMedia}>{t("browser.clearAllConfirm.confirm")}</AlertDialogAction>
190+
</AlertDialogFooter>
191+
</AlertDialogContent>
192+
</AlertDialog>
193+
) : undefined
146194

147195
return (
148196
<>

src/features/browser/components/preview/media-preview.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,18 +50,21 @@ export function MediaPreview({
5050
return (
5151
<div
5252
className={cn(
53-
"flex items-center justify-center bg-gray-100 dark:bg-gray-800",
53+
"relative flex items-center justify-center bg-gradient-to-br from-gray-900 to-black",
5454
ignoreRatio ? "w-full h-full" : "aspect-video",
5555
)}
5656
style={{
5757
width: ignoreRatio ? "100%" : `${((size * dimensions[0]) / dimensions[1]).toFixed(0)}px`,
5858
height: ignoreRatio ? "100%" : `${size}px`,
5959
}}
6060
>
61-
<div className="flex flex-col items-center justify-center gap-2">
62-
<Loader2 className="h-8 w-8 animate-spin text-gray-400" />
63-
<div className="text-xs text-gray-500 dark:text-gray-400">
64-
{showFileName ? file.name : "Загрузка метаданных..."}
61+
<div className="flex flex-col items-center justify-center gap-3 px-4 text-center">
62+
<Loader2 className="h-10 w-10 animate-spin text-blue-400" />
63+
<div className="flex flex-col gap-1">
64+
<div className="truncate text-sm font-medium text-white/90" style={{ maxWidth: "200px" }}>
65+
{file.name}
66+
</div>
67+
<div className="text-xs text-white/60 animate-pulse">Загрузка метаданных...</div>
6568
</div>
6669
</div>
6770
</div>

src/features/browser/components/preview/video-placeholder.tsx

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -189,17 +189,19 @@ export const VideoPlaceholder = memo(
189189
onKeyDown={handleKeyDown}
190190
/>
191191

192-
{/* Показываем имя файла если видео ещё не загружено и нет превью */}
193-
{!isLoaded && !previewData && !file.thumbnailPath && (
194-
<div className="absolute inset-0 flex flex-col items-center justify-center bg-linear-to-b from-black/40 to-black/60 text-center">
195-
<div className="truncate px-2 text-xs text-white/80" style={{ maxWidth: "90%" }}>
192+
{/* Показываем имя файла и статус загрузки - всегда когда не полностью загружено */}
193+
{(!isLoaded || !previewData || file.isLoadingMetadata) && (
194+
<div className="absolute inset-0 flex flex-col items-center justify-center bg-gradient-to-b from-black/50 to-black/70 text-center">
195+
<div className="truncate px-2 text-sm text-white/90 font-medium" style={{ maxWidth: "90%" }}>
196196
{file.name}
197197
</div>
198198
{hasError ? (
199-
<div className="mt-1 text-[10px] text-yellow-400/80">Ожидаем превью...</div>
200-
) : (
201-
<div className="mt-1 text-[10px] text-white/50">Загрузка...</div>
202-
)}
199+
<div className="mt-2 text-xs text-yellow-400/90">Ожидаем превью...</div>
200+
) : file.isLoadingMetadata || (!previewData && !file.thumbnailPath) ? (
201+
<div className="mt-2 text-xs text-white/70 animate-pulse">Загрузка метаданных...</div>
202+
) : !isLoaded ? (
203+
<div className="mt-2 text-xs text-white/70 animate-pulse">Загрузка видео...</div>
204+
) : null}
203205
</div>
204206
)}
205207

0 commit comments

Comments
 (0)