diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 37ece221..0971a052 100755 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -2,5 +2,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip - +#distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip +distributionUrl=https://mirrors.cloud.tencent.com/gradle/gradle-7.4-all.zip diff --git a/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart b/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart index fca6b402..05bbf80d 100755 --- a/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart +++ b/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart @@ -9,7 +9,7 @@ import 'package:star_lock/main/lockDetail/doorLockLog/doorLockLog_state.dart'; import 'package:star_lock/main/lockDetail/doorLockLog/exportRecordDialog/exportRecordDialog_page.dart'; import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_entity.dart'; import 'package:star_lock/main/lockDetail/videoLog/widget/full_screenImage_page.dart'; -import 'package:star_lock/main/lockDetail/videoLog/widget/video_thumbnail.dart'; +import 'package:star_lock/main/lockDetail/videoLog/widget/video_thumbnail_image.dart'; import 'package:star_lock/tools/EasyRefreshTool.dart'; import 'package:star_lock/tools/advancedCalendar/src/widget.dart'; import 'package:star_lock/tools/commonDataManage.dart'; @@ -399,7 +399,7 @@ class _DoorLockLogPageState extends State with RouteAware { } _buildVideoItem(RecordListData recordData) { - return VideoThumbnail(videoUrl: recordData.videoUrl!); + return VideoThumbnailImage(videoUrl: recordData.videoUrl!); } _buildImageItem(RecordListData recordData) { diff --git a/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_page.dart b/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_page.dart index c52a90d5..86faa5b8 100755 --- a/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_page.dart +++ b/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_page.dart @@ -6,7 +6,7 @@ import 'package:star_lock/appRouters.dart'; import 'package:star_lock/main/lockDetail/videoLog/editVideoLog/editVideoLog_state.dart'; import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_entity.dart'; import 'package:star_lock/main/lockDetail/videoLog/widget/full_screenImage_page.dart'; -import 'package:star_lock/main/lockDetail/videoLog/widget/video_thumbnail.dart'; +import 'package:star_lock/main/lockDetail/videoLog/widget/video_thumbnail_image.dart'; import 'package:star_lock/tools/dateTool.dart'; import '../../../../app_settings/app_colors.dart'; @@ -241,61 +241,8 @@ class _EditVideoLogPageState extends State { Future _onDelClick() async { if (state.selectVideoLogList.value.isNotEmpty) { - // 弹出自定义确认对话框 - bool confirmDelete = await showDialog( - context: context, - builder: (BuildContext context) { - return Dialog( - backgroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(16), - ), - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - '确认删除'.tr, - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - SizedBox(height: 16), - Text('确定要删除选中的视频吗?'.tr), - SizedBox(height: 24), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () { - // 用户点击取消,返回 false - Navigator.of(context).pop(false); - }, - child: Text('取消'.tr), - ), - SizedBox(width: 8), - ElevatedButton( - onPressed: () { - // 用户点击确认,返回 true - Navigator.of(context).pop(true); - }, - child: Text('确认'.tr), - ), - ], - ), - ], - ), - ), - ); - }, - ); - - // 如果用户确认删除,执行删除逻辑 - if (confirmDelete == true) { - await logic.deleteLockCloudStorageList(); - } + await logic.deleteLockCloudStorageList(); + setState(() {}); } else { logic.showToast('请选择要删除的视频'.tr); } @@ -412,7 +359,7 @@ class _EditVideoLogPageState extends State { } _buildVideoItem(RecordListData recordData) { - return VideoThumbnail(videoUrl: recordData.videoUrl!); + return VideoThumbnailImage(videoUrl: recordData.videoUrl!); } _buildImageItem(RecordListData recordData) { diff --git a/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart b/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart index 41124660..b19264a5 100755 --- a/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart +++ b/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart @@ -22,38 +22,12 @@ class VideoLogLogic extends BaseGetXController { (record.imagesUrl != null && record.imagesUrl!.isNotEmpty) || (record.videoUrl != null && record.videoUrl!.isNotEmpty)) .toList(); - - // // 为 videoUrl 不为空的项设置封面 - // for (var record in element.recordList!) { - // if (record.videoUrl != null && record.videoUrl!.isNotEmpty) { - // _setVideoThumbnail(record); // 设置视频封面 - // } - // } }); state.videoLogList.refresh(); } } - // Future _setVideoThumbnail(RecordListData record) async { - // try { - // final thumbnailData = await getVideoThumbnail(record.videoUrl!); - // record.thumbnailData = thumbnailData; // 设置视频封面数据 - // } catch (e) { - // print('获取视频封面失败: $e'); - // } - // } - // - // Future getVideoThumbnail(String videoUrl) async { - // final thumbnail = await VideoThumbnail.thumbnailData( - // video: videoUrl, - // imageFormat: ImageFormat.JPEG, - // maxWidth: 128, // 缩略图的最大宽度 - // quality: 25, // 缩略图的质量(0-100) - // ); - // return thumbnail; - // } - @override onReady() { super.onReady(); diff --git a/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart b/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart index 994f7383..7911a215 100755 --- a/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart +++ b/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart @@ -6,7 +6,7 @@ import 'package:star_lock/flavors.dart'; import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_entity.dart'; import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_state.dart'; import 'package:star_lock/main/lockDetail/videoLog/widget/full_screenImage_page.dart'; -import 'package:star_lock/main/lockDetail/videoLog/widget/video_thumbnail.dart'; +import 'package:star_lock/main/lockDetail/videoLog/widget/video_thumbnail_image.dart'; import 'package:star_lock/tools/dateTool.dart'; import 'package:star_lock/tools/noData.dart'; import 'package:video_player/video_player.dart'; @@ -341,7 +341,7 @@ class _VideoLogPageState extends State { } _buildVideoItem(RecordListData recordData) { - return VideoThumbnail(videoUrl: recordData.videoUrl!); + return VideoThumbnailImage(videoUrl: recordData.videoUrl!); } _buildImageItem(RecordListData recordData) { diff --git a/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_page.dart b/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_page.dart index bd680cab..619d0539 100755 --- a/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_page.dart +++ b/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_page.dart @@ -8,7 +8,7 @@ import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_entity.dart import 'package:star_lock/main/lockDetail/videoLog/videoLogDetail/controlsOverlay_page.dart'; import 'package:star_lock/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_state.dart'; import 'package:star_lock/main/lockDetail/videoLog/widget/full_screenImage_page.dart'; -import 'package:star_lock/main/lockDetail/videoLog/widget/video_thumbnail.dart'; +import 'package:star_lock/main/lockDetail/videoLog/widget/video_thumbnail_image.dart'; import 'package:star_lock/tools/dateTool.dart'; import 'package:video_player/video_player.dart'; @@ -165,7 +165,7 @@ class _VideoLogDetailPageState extends State { } _buildVideoItem(RecordListData recordData) { - return VideoThumbnail(videoUrl: recordData.videoUrl!); + return VideoThumbnailImage(videoUrl: recordData.videoUrl!); } _buildImageItem(RecordListData recordData) { diff --git a/lib/main/lockDetail/videoLog/widget/video_thumbnail.dart b/lib/main/lockDetail/videoLog/widget/video_thumbnail.dart deleted file mode 100644 index 06b63b59..00000000 --- a/lib/main/lockDetail/videoLog/widget/video_thumbnail.dart +++ /dev/null @@ -1,76 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:video_player/video_player.dart'; - -class VideoThumbnail extends StatefulWidget { - final String videoUrl; - - VideoThumbnail({required this.videoUrl}); - - @override - _VideoThumbnailState createState() => _VideoThumbnailState(); -} - -class _VideoThumbnailState extends State { - late VideoPlayerController _controller; - late Future _initializeVideoPlayerFuture; - - @override - void initState() { - super.initState(); - // 创建并初始化 VideoPlayerController - _controller = VideoPlayerController.network(widget.videoUrl) - ..initialize().then((_) { - // 当视频控制器初始化完成后,更新UI以便显示第一帧 - setState(() {}); - }); - } - - @override - void dispose() { - // 清理资源 - _controller.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return GestureDetector( - // onTap: () { - // setState(() { - // if (_controller.value.isPlaying) { - // _controller.pause(); - // } else { - // _controller.play(); - // } - // }); - // }, - child: Stack( - alignment: Alignment.center, - children: [ - // 如果视频已经初始化,则显示视频玩家 - _controller.value.isInitialized - ? RotatedBox( - quarterTurns: -1, - child: AspectRatio( - aspectRatio: 1 / 1, // 强制正方形比例 - child: FittedBox( - fit: BoxFit.cover, // 确保视频封面铺满空间 - child: SizedBox( - width: _controller.value.size.width, - height: _controller.value.size.height, - child: VideoPlayer(_controller), - ), - ), - ), - ) - : Center( - child: CircularProgressIndicator(), // 加载中显示转圈 - ), - if (!_controller.value.isPlaying && _controller.value.isInitialized) - Icon(Icons.play_arrow_rounded, - size: 80, color: Colors.white.withOpacity(0.8)), - ], - ), - ); - } -} diff --git a/lib/main/lockDetail/videoLog/widget/video_thumbnail_image.dart b/lib/main/lockDetail/videoLog/widget/video_thumbnail_image.dart new file mode 100644 index 00000000..4f119569 --- /dev/null +++ b/lib/main/lockDetail/videoLog/widget/video_thumbnail_image.dart @@ -0,0 +1,97 @@ +import 'dart:io'; // 导入 dart:io 以使用 File 类 +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +import 'package:path_provider/path_provider.dart'; // 导入 path_provider +import 'package:video_thumbnail/video_thumbnail.dart'; // 导入 video_thumbnail + +class VideoThumbnailImage extends StatefulWidget { + final String videoUrl; + + VideoThumbnailImage({required this.videoUrl}); + + @override + _VideoThumbnailState createState() => _VideoThumbnailState(); +} + +class _VideoThumbnailState extends State { + final Map _thumbnailCache = {}; // 缩略图缓存 + late Future _thumbnailFuture; // 用于存储缩略图生成的 Future + + @override + void initState() { + super.initState(); + _thumbnailFuture = _generateThumbnail(); // 在 initState 中初始化 Future + } + + // 生成缩略图 + Future _generateThumbnail() async { + try { + // 检查缓存中是否已有缩略图 + if (_thumbnailCache.containsKey(widget.videoUrl)) { + return _thumbnailCache[widget.videoUrl]; + } + + // 获取临时目录路径 + final tempDir = await getTemporaryDirectory(); + final thumbnailPath = await VideoThumbnail.thumbnailFile( + video: widget.videoUrl, + // 视频 URL + thumbnailPath: tempDir.path, + // 缩略图保存路径 + imageFormat: ImageFormat.JPEG, + // 缩略图格式 + maxHeight: 200, + // 缩略图最大高度 + quality: 100, // 缩略图质量 (0-100) + ); + + // 更新缓存 + _thumbnailCache[widget.videoUrl] = thumbnailPath!; + return thumbnailPath; + } catch (e) { + print('Failed to generate thumbnail: $e'); + return null; + } + } + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: _thumbnailFuture, // 生成缩略图的 Future + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + // 加载中显示转圈 + return Center(child: CircularProgressIndicator()); + } else if (snapshot.hasError || !snapshot.hasData) { + // 加载失败或没有数据时显示提示 + return Image.asset( + 'images/icon_unHaveData.png', // 错误图片路径 + fit: BoxFit.cover, + ); + } else { + // 加载成功,显示缩略图 + final thumbnailPath = snapshot.data!; + return Stack( + alignment: Alignment.center, + children: [ + RotatedBox( + quarterTurns: -1, + child: Image.file( + File(thumbnailPath), // 显示生成的缩略图 + width: 200, + height: 200, + fit: BoxFit.cover, + ), + ), + Icon( + Icons.play_arrow_rounded, + size: 80, + color: Colors.white.withOpacity(0.8), + ), + ], + ); + } + }, + ); + } +}