From d3ca3e62e39d66944ec809699d3dbcd596230eb4 Mon Sep 17 00:00:00 2001 From: Abraham Date: Sun, 18 Jan 2026 21:51:56 -0800 Subject: [PATCH] =?UTF-8?q?Ahora=20el=20Batch=20se=20pueden=20a=C3=B1adir?= =?UTF-8?q?=20tags?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/videos/gestor_videos_page.dart | 95 ++------------- .../widgets/premium_batch_upload_dialog.dart | 112 +++++++++++++++++- 2 files changed, 118 insertions(+), 89 deletions(-) diff --git a/lib/pages/videos/gestor_videos_page.dart b/lib/pages/videos/gestor_videos_page.dart index 934719e..db22386 100644 --- a/lib/pages/videos/gestor_videos_page.dart +++ b/lib/pages/videos/gestor_videos_page.dart @@ -6,7 +6,6 @@ import 'package:energy_media/models/media/media_models.dart'; import 'package:energy_media/theme/theme.dart'; import 'package:energy_media/helpers/globals.dart'; import 'package:energy_media/widgets/premium_button.dart'; -import 'package:energy_media/pages/videos/widgets/premium_upload_dialog.dart'; import 'package:energy_media/pages/videos/widgets/premium_batch_upload_dialog.dart'; import 'package:energy_media/pages/videos/widgets/video_player_dialog.dart'; import 'package:energy_media/pages/videos/widgets/gestor_videos_widgets/empty_state_widget.dart'; @@ -132,7 +131,7 @@ class _GestorVideosPageState extends State { Expanded( child: provider.mediaFiles.isEmpty ? EmptyStateWidget( - onUploadPressed: () => _showUploadDialog(provider), + onUploadPressed: () => _showBatchUploadDialog(provider), ) : ListView.builder( padding: const EdgeInsets.all(16), @@ -177,7 +176,7 @@ class _GestorVideosPageState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ if (isMobile) ...[ - // Vista móvil: solo botón centrado con diseño mejorado + // Vista móvil: botón único para subir videos Center( child: Container( width: double.infinity, @@ -200,64 +199,6 @@ class _GestorVideosPageState extends State { ), ], ), - child: Material( - color: Colors.transparent, - child: InkWell( - onTap: () => _showUploadDialog(provider), - borderRadius: BorderRadius.circular(16), - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 24, vertical: 16), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Icon( - Icons.cloud_upload_rounded, - color: Color(0xFF0B0B0D), - size: 24, - ), - const Gap(12), - Text( - 'Subir Video', - style: const TextStyle( - color: Color(0xFF0B0B0D), - fontSize: 16, - fontWeight: FontWeight.w700, - fontFamily: 'Poppins', - letterSpacing: 0.5, - ), - ), - ], - ), - ), - ), - ), - ), - ), - const Gap(12), - // Botón subida masiva móvil - Center( - child: Container( - width: double.infinity, - constraints: const BoxConstraints(maxWidth: 300), - decoration: BoxDecoration( - gradient: const LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [ - Color(0xFF6B2F8A), - Color(0xFF4EC9F5), - ], - ), - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: const Color(0xFF6B2F8A).withOpacity(0.4), - blurRadius: 12, - offset: const Offset(0, 4), - ), - ], - ), child: Material( color: Colors.transparent, child: InkWell( @@ -270,15 +211,15 @@ class _GestorVideosPageState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( - Icons.cloud_upload_outlined, - color: Colors.white, + Icons.cloud_upload_rounded, + color: Color(0xFF0B0B0D), size: 24, ), Gap(12), Text( - 'Subida Masiva', + 'Subir Videos', style: TextStyle( - color: Colors.white, + color: Color(0xFF0B0B0D), fontSize: 16, fontWeight: FontWeight.w700, fontFamily: 'Poppins', @@ -337,16 +278,9 @@ class _GestorVideosPageState extends State { ), ), PremiumButton( - text: 'Subir Video', - icon: Icons.cloud_upload, - onPressed: () => _showUploadDialog(provider), - ), - const Gap(12), - PremiumButton( - text: 'Subida Masiva', - icon: Icons.cloud_upload_outlined, + text: 'Subir Videos', + icon: Icons.cloud_upload_rounded, onPressed: () => _showBatchUploadDialog(provider), - backgroundColor: const Color(0xFF6B2F8A), ), ], ), @@ -1325,19 +1259,6 @@ class _GestorVideosPageState extends State { ); } - Future _showUploadDialog(VideosProvider provider) async { - await showDialog( - context: context, - barrierDismissible: false, - builder: (context) => PremiumUploadDialog( - provider: provider, - onSuccess: () { - _loadData(); - }, - ), - ); - } - Future _showBatchUploadDialog(VideosProvider provider) async { await showDialog( context: context, diff --git a/lib/pages/videos/widgets/premium_batch_upload_dialog.dart b/lib/pages/videos/widgets/premium_batch_upload_dialog.dart index d523e60..565a6ad 100644 --- a/lib/pages/videos/widgets/premium_batch_upload_dialog.dart +++ b/lib/pages/videos/widgets/premium_batch_upload_dialog.dart @@ -16,6 +16,7 @@ class BatchVideoItem { String fileName; String title; String description; + List tags; Uint8List videoBytes; Uint8List? posterBytes; String? posterFileName; @@ -31,6 +32,7 @@ class BatchVideoItem { required this.title, required this.videoBytes, this.description = '', + this.tags = const [], this.posterBytes, this.posterFileName, this.blobUrl, @@ -126,6 +128,7 @@ class _PremiumBatchUploadDialogState extends State { videoBytes: bytes, blobUrl: blobUrl, durationSeconds: duration, + tags: [], // Lista mutable para tags ); setState(() { @@ -299,6 +302,7 @@ class _PremiumBatchUploadDialogState extends State { title: video.title, description: video.description.isEmpty ? null : video.description, durationSeconds: video.durationSeconds, + tags: video.tags.isNotEmpty ? video.tags : null, ); return success; @@ -482,7 +486,7 @@ class _PremiumBatchUploadDialogState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( - 'Subida Masiva de Videos', + 'Subir Videos', style: TextStyle( color: Colors.white, fontSize: 20, @@ -493,7 +497,7 @@ class _PremiumBatchUploadDialogState extends State { const Gap(4), Text( _videoQueue.isEmpty - ? 'Selecciona múltiples videos para subir' + ? 'Selecciona uno o varios videos' : '${_videoQueue.length} video(s) en cola', style: TextStyle( color: Colors.white.withOpacity(0.8), @@ -884,6 +888,110 @@ class _PremiumBatchUploadDialogState extends State { isDense: true, ), ), + const Gap(8), + // Tags + _buildTagsField(video, isEditable), + ], + ); + } + + Widget _buildTagsField(BatchVideoItem video, bool isEditable) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Mostrar tags existentes como chips + if (video.tags.isNotEmpty) + Padding( + padding: const EdgeInsets.only(bottom: 8), + child: Wrap( + spacing: 6, + runSpacing: 6, + children: video.tags.map((tag) { + return Container( + padding: + const EdgeInsets.symmetric(horizontal: 10, vertical: 4), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + const Color(0xFF4EC9F5).withOpacity(0.2), + const Color(0xFFFFB733).withOpacity(0.2), + ], + ), + borderRadius: BorderRadius.circular(20), + border: Border.all( + color: const Color(0xFF4EC9F5).withOpacity(0.3), + ), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + tag, + style: TextStyle( + color: AppTheme.of(context).primaryText, + fontFamily: 'Poppins', + fontSize: 12, + fontWeight: FontWeight.w500, + ), + ), + if (isEditable) ...[ + const Gap(4), + GestureDetector( + onTap: () { + setState(() { + video.tags = List.from(video.tags)..remove(tag); + }); + }, + child: Icon( + Icons.close_rounded, + size: 14, + color: AppTheme.of(context).tertiaryText, + ), + ), + ], + ], + ), + ); + }).toList(), + ), + ), + // Campo para agregar nuevo tag + TextField( + enabled: isEditable, + style: TextStyle( + color: AppTheme.of(context).primaryText, + fontFamily: 'Poppins', + fontSize: 13, + ), + decoration: InputDecoration( + hintText: 'Agregar tag y presiona Enter', + hintStyle: TextStyle( + color: AppTheme.of(context).tertiaryText, + ), + prefixIcon: Icon( + Icons.label_rounded, + color: const Color(0xFFFFB733), + size: 20, + ), + filled: true, + fillColor: AppTheme.of(context).secondaryBackground, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide.none, + ), + contentPadding: + const EdgeInsets.symmetric(horizontal: 12, vertical: 12), + isDense: true, + ), + onSubmitted: (value) { + final tag = value.trim(); + if (tag.isNotEmpty && !video.tags.contains(tag)) { + setState(() { + video.tags = List.from(video.tags)..add(tag); + }); + } + }, + ), ], ); }