feat(app): 곡 상세 화면 뮤직비디오 앱 내 재생 + YouTube 이동 버튼

- 썸네일+재생 버튼 → OmniVideoPlayer로 교체 (앱 내 직접 재생)
- 하단에 'YouTube에서 보기' 텍스트 버튼 추가

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
caadiq 2026-04-04 13:08:14 +09:00
parent 5f70b6852f
commit aa750b19d4

View file

@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:lucide_icons/lucide_icons.dart';
import 'package:omni_video_player/omni_video_player.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../core/constants.dart';
import '../../models/album.dart';
@ -326,59 +327,33 @@ class _MusicVideoSection extends StatelessWidget {
],
),
const SizedBox(height: 12),
//
GestureDetector(
onTap: onTap,
child: Container(
width: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.1),
blurRadius: 8,
offset: const Offset(0, 2),
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(12),
child: AspectRatio(
aspectRatio: 16 / 9,
child: Stack(
fit: StackFit.expand,
children: [
CachedNetworkImage(
imageUrl: 'https://img.youtube.com/vi/$videoId/maxresdefault.jpg',
fit: BoxFit.cover,
placeholder: (context, url) => Container(color: Colors.black),
errorWidget: (context, url, error) => CachedNetworkImage(
imageUrl: 'https://img.youtube.com/vi/$videoId/hqdefault.jpg',
fit: BoxFit.cover,
),
),
//
Container(
color: Colors.black.withValues(alpha: 0.3),
child: Center(
child: Container(
width: 56,
height: 56,
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(28),
),
child: const Icon(
LucideIcons.play,
color: Colors.white,
size: 28,
),
),
),
),
],
//
ClipRRect(
borderRadius: BorderRadius.circular(12),
child: AspectRatio(
aspectRatio: 16 / 9,
child: OmniVideoPlayer(
configuration: VideoPlayerConfiguration(
videoSourceConfiguration: VideoSourceConfiguration.youtube(
videoUrl: Uri.parse('https://www.youtube.com/watch?v=$videoId'),
preferredQualities: [OmniVideoQuality.high720],
),
),
callbacks: const VideoPlayerCallbacks(),
),
),
),
const SizedBox(height: 8),
// YouTube에서
SizedBox(
width: double.infinity,
child: TextButton.icon(
onPressed: onTap,
icon: const Icon(LucideIcons.externalLink, size: 14),
label: const Text('YouTube에서 보기', style: TextStyle(fontSize: 13)),
style: TextButton.styleFrom(
foregroundColor: Colors.red,
padding: const EdgeInsets.symmetric(vertical: 8),
),
),
),