1,更新视频播放器插件版本

2,新增视频日志云存列表接口对接及视频列表逻辑处理
3,完成点击云存列表播放当前MP4格式的视频以及页面完善逻辑处理
4,新增编辑视频页面数据接口对接
This commit is contained in:
Daisy 2024-04-25 17:33:07 +08:00
parent 7fdc1e6e6d
commit af59247c46
15 changed files with 471 additions and 230 deletions

View File

@ -46,7 +46,7 @@
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
<application android:label="@string/app_name" android:name="android.app.Application" android:icon="@mipmap/ic_launcher">
<application android:usesCleartextTraffic="true" android:label="@string/app_name" android:name="android.app.Application" android:icon="@mipmap/ic_launcher">
<meta-data
android:name="flutterEmbedding"
android:value="2" />

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

@ -779,5 +779,13 @@
"添加和使用面容开锁时:":"Add and use Face when unlocking:",
"关锁":"close lock",
"功能":"function",
"配件":"parts"
"配件":"parts",
"云存":"Cloud storage",
"本地":"This locality",
"3天滚动储存":"3 days rolling storage",
"去升级":"Upgrade Now",
"下载列表":"Download list",
"已下载":"Downloaded",
"全部视频":"All videos",
"已为本设备免费提供3大滚动视频储存服务":"Three scrolling video storage services have been provided for this device free of charge"
}

View File

@ -778,5 +778,13 @@
"经过以上设定的时间,锁没有被开启,系统会给指定对象发送提醒消息,该功能需要锁联网":"经过以上设定的时间,锁没有被开启,系统会给指定对象发送提醒消息,该功能需要锁联网",
"打开提醒后当锁电量低于20%、10%和5%系统会给指定对象发送提醒消息。电量读取方式网关读取或APP读取。":"打开提醒后当锁电量低于20%、10%和5%系统会给指定对象发送提醒消息。电量读取方式网关读取或APP读取。",
"门未开时间":"门未开时间",
"添加和使用面容开锁时:":"添加和使用面容开锁时:"
"添加和使用面容开锁时:":"添加和使用面容开锁时:",
"云存":"云存",
"本地":"本地",
"3天滚动储存":"3天滚动储存",
"去升级":"去升级",
"下载列表":"下载列表",
"已下载":"已下载",
"全部视频":"全部视频",
"已为本设备免费提供3大滚动视频储存服务":"已为本设备免费提供3大滚动视频储存服务"
}

View File

@ -781,5 +781,13 @@
"经过以上设定的时间,锁没有被开启,系统会给指定对象发送提醒消息,该功能需要锁联网":"经过以上设定的时间,锁没有被开启,系统会给指定对象发送提醒消息,该功能需要锁联网",
"打开提醒后当锁电量低于20%、10%和5%系统会给指定对象发送提醒消息。电量读取方式网关读取或APP读取。":"打开提醒后当锁电量低于20%、10%和5%系统会给指定对象发送提醒消息。电量读取方式网关读取或APP读取。",
"门未开时间":"门未开时间",
"添加和使用面容开锁时:":"添加和使用面容开锁时:"
"添加和使用面容开锁时:":"添加和使用面容开锁时:",
"云存":"云存",
"本地":"本地",
"3天滚动储存":"3天滚动储存",
"去升级":"去升级",
"下载列表":"下载列表",
"已下载":"已下载",
"全部视频":"全部视频",
"已为本设备免费提供3大滚动视频储存服务":"已为本设备免费提供3大滚动视频储存服务"
}

View File

@ -1,7 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_entity.dart';
import 'package:star_lock/tools/dateTool.dart';
import '../../../../app_settings/app_colors.dart';
import '../../../../tools/titleAppBar.dart';
@ -41,20 +42,23 @@ class _EditVideoLogPageState extends State<EditVideoLogPage> {
body: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: 5,
child: Obx(() => ListView.builder(
itemCount: state.videoLogList.length,
itemBuilder: (c, index) {
return Column(children: [
Container(
margin: EdgeInsets.only(left:20.w, top: 15.w, bottom: 15.w),
child: Row(
children: [
Text("2023.10.23", style: TextStyle(fontSize: 20.sp)),
]
)),
mainListView(index)
],);
}),
CloudStorageData item = state.videoLogList[index];
return Column(
children: [
Container(
margin: EdgeInsets.only(
left: 20.w, top: 15.w, bottom: 15.w),
child: Row(children: [
Text(item.date ?? "",
style: TextStyle(fontSize: 20.sp)),
])),
mainListView(index, item)
],
);
})),
),
bottomBottomBtnWidget()
],
@ -62,35 +66,31 @@ class _EditVideoLogPageState extends State<EditVideoLogPage> {
);
}
var itemW = (1.sw - 15.w*4)/3;
var itemH = (1.sw - 15.w*4)/3+40.h;
Widget mainListView(int index){
return Container(
// margin: EdgeInsets.only(left: 10.w, right: 10.w, top: 40.h),
// color: Colors.blue,
child: GridView.builder(
padding: EdgeInsets.only(left: 15.w, right: 15.w),
itemCount: index+1,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
var itemW = (1.sw - 15.w * 4) / 3;
var itemH = (1.sw - 15.w * 4) / 3 + 40.h;
Widget mainListView(int index, CloudStorageData itemData) {
return GridView.builder(
padding: EdgeInsets.only(left: 15.w, right: 15.w),
itemCount: itemData.recordList!.length,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
//
crossAxisCount: 3,
//
mainAxisSpacing: 10.w,
//
crossAxisSpacing: 15.w,
//
childAspectRatio: itemW/itemH
),
itemBuilder: (context, index) {
return Obx(() => videoItem());
},
),
crossAxisCount: 3,
//
mainAxisSpacing: 10.w,
//
crossAxisSpacing: 15.w,
//
childAspectRatio: itemW / itemH),
itemBuilder: (context, index) {
RecordListData recordData = itemData.recordList![index];
return videoItem(recordData, index);
},
);
}
Widget videoItem(){
Widget videoItem(RecordListData recordData, int index) {
return SizedBox(
width: itemW,
height: itemH,
@ -98,12 +98,26 @@ class _EditVideoLogPageState extends State<EditVideoLogPage> {
children: [
Column(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(10.w),
child: Image(width: itemW, height: itemW, fit: BoxFit.fill, image: const AssetImage("images/main/icon_lockDetail_monitoringvoiceFrist.png")),
Container(
width: itemW,
height: itemW,
margin: const EdgeInsets.all(0),
color: Colors.white,
child: ClipRRect(
borderRadius: BorderRadius.circular(10.w),
child: Image(
fit: BoxFit.cover,
image: Image.network(recordData.imagesUrl ??
"images/icon_video_placeholder.jpg")
.image),
),
),
SizedBox(height:5.h),
Text("2023.10.23 10:00", style: TextStyle(fontSize: 20.sp))
SizedBox(height: 5.h),
Text(
DateTool()
.dateToYMDHNString(recordData.operateDate.toString()),
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18.sp))
],
),
Visibility(
@ -112,36 +126,41 @@ class _EditVideoLogPageState extends State<EditVideoLogPage> {
top: 0.w,
right: 0.w,
child: GestureDetector(
onTap: (){
},
child: Image(width: 40.w, height: 40.w, image: state.isSelectAll.value ? const AssetImage("images/icon_round_select.png") : const AssetImage("images/icon_round_unSelect.png"))
)
),
onTap: () {},
child: Obx(() => Image(
width: 36.w,
height: 36.w,
image: state.isSelectAll.value
? const AssetImage("images/icon_round_select.png")
: const AssetImage(
"images/icon_round_unSelect.png"))))),
)
],
),
);
}
Widget bottomBottomBtnWidget(){
Widget bottomBottomBtnWidget() {
return Container(
width: 1.sw,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
bottomBtnItemWidget("images/main/icon_lockDetail_monitoringDownloadVideo.png", "下载", Colors.white,(){
}),
SizedBox(width:100.w),
bottomBtnItemWidget("images/main/icon_lockDetail_monitoringDeletVideo.png", "删除", AppColors.mainColor,(){
})
]),
child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [
bottomBtnItemWidget(
"images/main/icon_lockDetail_monitoringDownloadVideo.png",
"下载",
Colors.white,
() {}),
SizedBox(width: 100.w),
bottomBtnItemWidget(
"images/main/icon_lockDetail_monitoringDeletVideo.png",
"删除",
AppColors.mainColor,
() {})
]),
);
}
Widget bottomBtnItemWidget(String iconUrl, String name, Color backgroundColor, Function() onClick) {
Widget bottomBtnItemWidget(
String iconUrl, String name, Color backgroundColor, Function() onClick) {
var wh = 40.w;
return GestureDetector(
onTap: onClick,
@ -153,10 +172,12 @@ class _EditVideoLogPageState extends State<EditVideoLogPage> {
SizedBox(height: 30.w),
Image.asset(iconUrl, width: wh, height: wh, fit: BoxFit.fitWidth),
SizedBox(height: 10.w),
Expanded(child: Text(name, style: TextStyle(fontSize: 22.sp), textAlign: TextAlign.center))
Expanded(
child: Text(name,
style: TextStyle(fontSize: 22.sp),
textAlign: TextAlign.center))
],
)),
);
}
}

View File

@ -1,10 +1,15 @@
import 'package:get/get.dart';
class EditVideoLogState{
class EditVideoLogState {
var selectVideoLog = 0.obs;
var selectVideoLogList = [].obs;
var isSelectAll = false.obs;
var videoLogList = [].obs;
EditVideoLogState() {
Map map = Get.arguments;
if (map['videoDataList'] != null) {
videoLogList.value = map['videoDataList'];
}
}
}

View File

@ -0,0 +1,90 @@
class VideoLogEntity {
int? errorCode;
String? description;
String? errorMsg;
List<CloudStorageData>? data;
VideoLogEntity({this.errorCode, this.description, this.errorMsg, this.data});
VideoLogEntity.fromJson(Map<String, dynamic> json) {
errorCode = json['errorCode'];
description = json['description'];
errorMsg = json['errorMsg'];
if (json['data'] != null) {
data = <CloudStorageData>[];
json['data'].forEach((v) {
data!.add(CloudStorageData.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['errorCode'] = errorCode;
data['description'] = description;
data['errorMsg'] = errorMsg;
if (this.data != null) {
data['data'] = this.data!.map((v) => v.toJson()).toList();
}
return data;
}
}
class CloudStorageData {
String? date;
List<RecordListData>? recordList;
CloudStorageData({this.date, this.recordList});
CloudStorageData.fromJson(Map<String, dynamic> json) {
date = json['date'];
if (json['recordList'] != null) {
recordList = <RecordListData>[];
json['recordList'].forEach((v) {
recordList!.add(RecordListData.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['date'] = date;
if (recordList != null) {
data['recordList'] = recordList!.map((v) => v.toJson()).toList();
}
return data;
}
}
class RecordListData {
int? recordId;
int? operateDate;
String? imagesUrl;
String? videoUrl;
int? recordType;
RecordListData(
{this.recordId,
this.operateDate,
this.imagesUrl,
this.videoUrl,
this.recordType});
RecordListData.fromJson(Map<String, dynamic> json) {
recordId = json['recordId'];
operateDate = json['operateDate'];
imagesUrl = json['imagesUrl'];
videoUrl = json['videoUrl'];
recordType = json['recordType'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['recordId'] = recordId;
data['operateDate'] = operateDate;
data['imagesUrl'] = imagesUrl;
data['videoUrl'] = videoUrl;
data['recordType'] = recordType;
return data;
}
}

View File

@ -10,7 +10,7 @@ class VideoLogLogic extends BaseGetXController {
lockId: state.getLockId.value,
);
if (entity.errorCode!.codeIsSuccessful) {
state.videoLogList.value = entity.data!.list!;
state.videoLogList.value = entity.data!;
state.videoLogList.refresh();
}
}

View File

@ -2,6 +2,9 @@ import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:star_lock/appRouters.dart';
import 'package:star_lock/flavors.dart';
import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_entity.dart';
import 'package:star_lock/tools/dateTool.dart';
import 'package:star_lock/tools/noData.dart';
import '../../../../app_settings/app_colors.dart';
@ -43,25 +46,26 @@ class _VideoLogPageState extends State<VideoLogPage> {
Visibility(visible: state.isNavLocal.value, child: localTip()),
// title加编辑按钮
editVideoTip(),
Visibility(
Obx(() => Visibility(
visible: !state.isNavLocal.value,
child: Expanded(
child: ListView.builder(
itemCount: 5,
itemCount: state.videoLogList.length,
itemBuilder: (c, index) {
CloudStorageData item = state.videoLogList[index];
return Column(
children: [
Container(
margin: EdgeInsets.only(
left: 20.w, top: 15.w, bottom: 15.w),
child: Row(children: [
Text("2023.10.2$index",
Text(item.date ?? "",
style: TextStyle(fontSize: 20.sp)),
])),
mainListView(index)
mainListView(index, item)
],
);
}))),
})))),
//
Visibility(
visible: state.isNavLocal.value,
@ -79,7 +83,7 @@ class _VideoLogPageState extends State<VideoLogPage> {
Text("2023.10.2$index",
style: TextStyle(fontSize: 20.sp)),
])),
mainListView(index)
mainListView(index, CloudStorageData()),
],
);
})
@ -103,7 +107,7 @@ class _VideoLogPageState extends State<VideoLogPage> {
state.isNavLocal.value = false;
});
},
child: Obx(() => Text("云存",
child: Obx(() => Text("云存".tr,
style: state.isNavLocal.value == true
? TextStyle(
color: Colors.grey,
@ -119,7 +123,7 @@ class _VideoLogPageState extends State<VideoLogPage> {
state.isNavLocal.value = true;
});
},
child: Obx(() => Text("本地",
child: Obx(() => Text("本地".tr,
style: state.isNavLocal.value == true
? TextStyle(
color: Colors.white,
@ -154,14 +158,14 @@ class _VideoLogPageState extends State<VideoLogPage> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("3天滚动储存", style: TextStyle(fontSize: 24.sp)),
Text("3天滚动储存".tr, style: TextStyle(fontSize: 24.sp)),
SizedBox(height: 10.h),
Text("星锁已为本设备免费提供3大滚动视频储存服务",
Text("${F.navTitle}${"已为本设备免费提供3大滚动视频储存服务".tr}",
style: TextStyle(fontSize: 22.sp, color: Colors.grey)),
],
)),
SizedBox(width: 15.w),
Text("去升级", style: TextStyle(fontSize: 22.sp)),
Text("去升级".tr, style: TextStyle(fontSize: 22.sp)),
Image(
width: 40.w,
height: 24.w,
@ -193,9 +197,9 @@ class _VideoLogPageState extends State<VideoLogPage> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// SizedBox(height: 20.h),
Text("下载列表", style: TextStyle(fontSize: 24.sp)),
Text("下载列表".tr, style: TextStyle(fontSize: 24.sp)),
SizedBox(height: 15.h),
Text("暂无下载内容",
Text("暂无下载内容".tr,
style: TextStyle(fontSize: 22.sp, color: Colors.grey)),
],
)),
@ -218,7 +222,7 @@ class _VideoLogPageState extends State<VideoLogPage> {
child: Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(state.isNavLocal.value == true ? "已下载" : "全部视频",
Text(state.isNavLocal.value == true ? "已下载".tr : "全部视频".tr,
style: TextStyle(fontSize: 26.sp, fontWeight: FontWeight.w500)),
Expanded(child: SizedBox(width: 10.w)),
IconButton(
@ -230,7 +234,8 @@ class _VideoLogPageState extends State<VideoLogPage> {
iconSize: 30,
color: Colors.black54,
onPressed: () {
Get.toNamed(Routers.editVideoLogPage);
Get.toNamed(Routers.editVideoLogPage,
arguments: {"videoDataList": state.videoLogList.value});
},
)
// TextButton(
@ -248,10 +253,10 @@ class _VideoLogPageState extends State<VideoLogPage> {
var itemH = (1.sw - 15.w * 4) / 3 + 40.h;
//
Widget mainListView(int index) {
Widget mainListView(int index, CloudStorageData itemData) {
return GridView.builder(
padding: EdgeInsets.only(left: 15.w, right: 15.w),
itemCount: index + 1,
itemCount: itemData.recordList!.length,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
@ -264,32 +269,44 @@ class _VideoLogPageState extends State<VideoLogPage> {
//
childAspectRatio: itemW / itemH),
itemBuilder: (context, index) {
return videoItem(() {
Get.toNamed(Routers.videoLogDetailPage);
});
RecordListData recordData = itemData.recordList![index];
return videoItem(recordData);
},
);
}
Widget videoItem(Function() action) {
Widget videoItem(RecordListData recordData) {
return GestureDetector(
onTap: action,
onTap: () {
Get.toNamed(Routers.videoLogDetailPage, arguments: {
"recordData": recordData,
"videoDataList": state.videoLogList.value
});
},
child: SizedBox(
width: itemW,
height: itemH,
child: Column(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(10.w),
child: Image(
width: itemW,
height: itemW,
fit: BoxFit.fill,
image: const AssetImage(
"images/main/icon_lockDetail_monitoringvoiceFrist.png")),
Container(
width: itemW,
height: itemW,
margin: const EdgeInsets.all(0),
color: Colors.white,
child: ClipRRect(
borderRadius: BorderRadius.circular(10.w),
child: Image(
fit: BoxFit.cover,
image: Image.network(recordData.imagesUrl ??
"images/icon_video_placeholder.jpg")
.image),
),
),
SizedBox(height: 5.h),
Text("2023.10.23 10:00", style: TextStyle(fontSize: 20.sp))
Text(
DateTool().dateToYMDHNString(recordData.operateDate.toString()),
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18.sp))
],
),
),

View File

@ -1,10 +1,13 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_entity.dart';
import 'package:star_lock/tools/dateTool.dart';
import 'package:video_player/video_player.dart';
class ControlsOverlay extends StatelessWidget {
const ControlsOverlay({required this.controller});
const ControlsOverlay(
{Key? key, required this.controller, required this.recordData})
: super(key: key);
static const List<Duration> _exampleCaptionOffsets = <Duration>[
Duration(seconds: -10),
@ -29,6 +32,7 @@ class ControlsOverlay extends StatelessWidget {
];
final VideoPlayerController controller;
final RecordListData recordData;
@override
Widget build(BuildContext context) {
@ -40,18 +44,18 @@ class ControlsOverlay extends StatelessWidget {
child: controller.value.isPlaying
? const SizedBox.shrink()
: Container(
color: Colors.black26,
child: const Center(
child:
// CircularProgressIndicator()
Icon(
Icons.play_arrow,
color: Colors.white,
size: 60.0,
semanticLabel: 'Play',
),
),
),
color: Colors.black26,
child: const Center(
child:
// CircularProgressIndicator()
Icon(
Icons.play_arrow,
color: Colors.white,
size: 60.0,
semanticLabel: 'Play',
),
),
),
),
GestureDetector(
onTap: () {
@ -123,32 +127,47 @@ class ControlsOverlay extends StatelessWidget {
left: 0.h,
right: 0.h,
child: Container(
margin: EdgeInsets.only(left:20.w, right:20.w),
margin: EdgeInsets.only(left: 20.w, right: 20.w),
// color: const Color(0xC83C3F41),
child: Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("星锁 2023/10/23", style: TextStyle(color: Colors.white, fontSize: 20.sp)),
Text(
DateTool()
.dateToYMDHNString(recordData.operateDate.toString()),
style: TextStyle(color: Colors.white, fontSize: 20.sp)),
Expanded(child: SizedBox(width: 10.w)),
Container(
width: 50.w,
height: 50.w,
padding: EdgeInsets.all(10.w),
child: Image(width: 50.w, height: 50.w, image: const AssetImage("images/main/icon_lockDetail_monitoringShareVideo_white.png")),
child: Image(
width: 50.w,
height: 50.w,
image: const AssetImage(
"images/main/icon_lockDetail_monitoringShareVideo_white.png")),
),
SizedBox(width: 20.w),
Container(
width: 50.w,
height: 50.w,
padding: EdgeInsets.all(10.w),
child: Image(width: 50.w, height: 50.w, image: const AssetImage("images/main/icon_lockDetail_monitoringDownloadVideo_white.png")),
child: Image(
width: 50.w,
height: 50.w,
image: const AssetImage(
"images/main/icon_lockDetail_monitoringDownloadVideo_white.png")),
),
SizedBox(width: 20.w),
Container(
width: 50.w,
height: 50.w,
padding: EdgeInsets.all(10.w),
child: Image(width: 50.w, height: 50.w, image: const AssetImage("images/main/icon_lockDetail_monitoringDeletVideo_white.png")),
child: Image(
width: 50.w,
height: 50.w,
image: const AssetImage(
"images/main/icon_lockDetail_monitoringDeletVideo_white.png")),
),
],
),
@ -164,37 +183,50 @@ class ControlsOverlay extends StatelessWidget {
color: const Color.fromRGBO(0, 0, 0, 0.5),
height: 60.h,
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
//
InkWell(
child: controller.value.isPlaying ? const Icon(Icons.pause, size: 30, color: Color(0xffefefef)) : const Icon(Icons.play_arrow, size: 30, color: Color(0xffefefef)),
child: controller.value.isPlaying
? const Icon(Icons.pause,
size: 30, color: Color(0xffefefef))
: const Icon(Icons.play_arrow,
size: 30, color: Color(0xffefefef)),
onTap: () {
// if(controller.value.isBuffering == false){
// return;
// }
controller.value.isPlaying ? controller.pause() : controller.play();
controller.value.isPlaying
? controller.pause()
: controller.play();
},
),
//
Text(formatString(controller.value.position), style: TextStyle(fontSize: 22.sp, color: const Color(0xffefefef)),),
Text(
formatString(controller.value.position),
style: TextStyle(
fontSize: 22.sp, color: const Color(0xffefefef)),
),
//
Expanded(
child: Slider(activeColor: const Color(0xFFFFFFFF), max: controller.value.duration.inMilliseconds.truncateToDouble(),
value: controller.value.position.inMilliseconds.truncateToDouble(),
child: Slider(
activeColor: const Color(0xFFFFFFFF),
max: controller.value.duration.inMilliseconds
.truncateToDouble(),
value: controller.value.position.inMilliseconds
.truncateToDouble(),
onChanged: (newRating) {
controller
.seekTo(Duration(
milliseconds:
newRating
.truncate()));
.seekTo(Duration(milliseconds: newRating.truncate()));
},
),
),
//
Text(formatString(controller.value.duration), style: TextStyle(fontSize: 22.sp, color: const Color(0xffefefef)),),
Text(
formatString(controller.value.duration),
style: TextStyle(
fontSize: 22.sp, color: const Color(0xffefefef)),
),
//
// DropdownButtonHideUnderline(
// child: DropdownButton2(
@ -261,4 +293,4 @@ class ControlsOverlay extends StatelessWidget {
var shortName = time.toString().substring(2, 7);
return shortName;
}
}
}

View File

@ -1,11 +1,12 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
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/tools/dateTool.dart';
import '../../../../app_settings/app_colors.dart';
import '../../../../tools/titleAppBar.dart';
import 'controlsOverlay_page.dart';
import 'videoLogDetail_logic.dart';
import 'package:video_player/video_player.dart';
@ -20,34 +21,20 @@ class _VideoLogDetailPageState extends State<VideoLogDetailPage> {
final logic = Get.put(VideoLogDetailLogic());
final state = Get.find<VideoLogDetailLogic>().state;
late VideoPlayerController _controller;
// Future<ClosedCaptionFile> _loadCaptions() async {
// final String fileContents = await DefaultAssetBundle.of(context)
// .loadString('images/bumble_bee_captions.vtt');
// return WebVTTCaptionFile(
// fileContents); // For vtt files, use WebVTTCaptionFile
// }
@override
void initState() {
super.initState();
_controller = VideoPlayerController.networkUrl(
Uri.parse('https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4'),
// closedCaptionFile: _loadCaptions(),
// videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true),
state.videoController = VideoPlayerController.networkUrl(
Uri.parse(state.recordData.value.videoUrl!),
videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true),
);
_controller.addListener(() {
setState(() {
print("controller.value.isBuffering:${_controller.value.isBuffering}");
});
state.videoController.addListener(() {
setState(() {});
});
_controller.setLooping(false);
// _controller.setVolume(1);
_controller.initialize();
state.videoController.setLooping(false);
state.videoController.initialize();
}
@override
@ -55,90 +42,119 @@ class _VideoLogDetailPageState extends State<VideoLogDetailPage> {
return Scaffold(
backgroundColor: Colors.white,
appBar: TitleAppBar(
barTitle: "本地视频播放",
barTitle: "视频播放",
haveBack: true,
backgroundColor: AppColors.mainColor,
),
body: Column(
children: [
AspectRatio(
aspectRatio: 16/9,
aspectRatio: state.videoController.value.aspectRatio,
child: Stack(
alignment: Alignment.bottomCenter,
children: <Widget>[
VideoPlayer(_controller),
// ClosedCaption(text: _controller.value.caption.text),
ControlsOverlay(controller: _controller),
(_controller.value.isPlaying || _controller.value.isBuffering) ? Container() : VideoProgressIndicator(_controller, colors:VideoProgressColors(playedColor:AppColors.mainColor), allowScrubbing: true),
VideoPlayer(state.videoController),
ControlsOverlay(
controller: state.videoController,
recordData: state.recordData.value,
),
(state.videoController.value.isPlaying ||
state.videoController.value.isBuffering)
? Container()
: VideoProgressIndicator(state.videoController,
colors: VideoProgressColors(
playedColor: AppColors.mainColor),
allowScrubbing: true),
],
),
),
Container(
margin: EdgeInsets.only(left:20.w, top: 15.w),
margin: EdgeInsets.only(left: 20.w, top: 15.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Row(
children: [
Text("2023.10.23", style: TextStyle(fontSize: 20.sp)),
Text(
DateTool().dateToYMDString(
state.recordData.value.operateDate.toString()),
style: TextStyle(fontSize: 20.sp)),
],
),
SizedBox(height: 15.h),
Row(
children: [
videoItem(true),
videoItem(true, state.recordData.value),
],
),
],
)),
Expanded(
child: ListView.builder(
itemCount: 4,
itemBuilder: (c, index) {
return Column(children: [
Container(
margin: EdgeInsets.only(left:20.w, top: 15.w, bottom: 15.w),
child: Row(
children: [
Text("2023.10.23", style: TextStyle(fontSize: 20.sp)),
]
)),
mainListView()
],);
}),
),
child: ListView.builder(
itemCount: state.videoLogList.length,
itemBuilder: (c, index) {
CloudStorageData item = state.videoLogList[index];
return Column(
children: [
Container(
margin: EdgeInsets.only(
left: 20.w, top: 15.w, bottom: 15.w),
child: Row(children: [
Text(item.date ?? "",
style: TextStyle(fontSize: 20.sp)),
])),
mainListView(index, item)
],
);
}))
// Expanded(
// child: ListView.builder(
// itemCount: state.videoLogList.value.length,
// itemBuilder: (c, index) {
// return Column(
// children: [
// Container(
// margin: EdgeInsets.only(
// left: 20.w, top: 15.w, bottom: 15.w),
// child: Row(children: [
// Text("2023.10.23",
// style: TextStyle(fontSize: 20.sp)),
// ])),
// mainListView()
// ],
// );
// }),
// ),
],
),
);
}
var itemW = (1.sw - 15.w*4)/3;
var itemH = (1.sw - 15.w*4)/3+40.h;
Widget mainListView(){
var itemW = (1.sw - 15.w * 4) / 3;
var itemH = (1.sw - 15.w * 4) / 3 + 40.h;
Widget mainListView(int index, CloudStorageData itemData) {
return GridView.builder(
padding: EdgeInsets.only(left: 15.w, right: 15.w),
itemCount: 4,
itemCount: itemData.recordList!.length,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
//
//
crossAxisCount: 3,
//
mainAxisSpacing: 10.w,
//
crossAxisSpacing: 15.w,
//
childAspectRatio: itemW/itemH
),
childAspectRatio: itemW / itemH),
itemBuilder: (context, index) {
return videoItem(false);
return videoItem(false, itemData.recordList![index]);
},
);
}
Widget videoItem(bool isPlay){
Widget videoItem(bool isPlay, RecordListData itemData) {
return SizedBox(
width: itemW,
height: itemH,
@ -148,33 +164,50 @@ class _VideoLogDetailPageState extends State<VideoLogDetailPage> {
children: [
ClipRRect(
borderRadius: BorderRadius.circular(10.w),
child: Stack(
children: [
Image(width: itemW, height: itemW, fit: BoxFit.fill, image: const AssetImage("images/main/icon_lockDetail_monitoringvoiceFrist.png")),
Positioned(
left: 8.w,
bottom: 5.h,
child: Text("00:06", style: TextStyle(color: Colors.white, fontSize: 20.sp))
),
Visibility(
visible: isPlay,
child: Positioned(
left: 0,
right: 0,
top: 0,
bottom: 0,
child: Container(
// padding: EdgeInsets.only(right: 10.w, left: 10.w),
color: const Color.fromRGBO(0, 0, 0, 0.3),
child: Center(child: Text("播放中", style: TextStyle(color: Colors.white, fontSize: 22.sp))),
)
),
)
]
),
child: Stack(children: [
Container(
width: itemW,
height: itemW,
margin: const EdgeInsets.all(0),
color: Colors.white,
child: ClipRRect(
borderRadius: BorderRadius.circular(10.w),
child: Image(
fit: BoxFit.cover,
image: Image.network(itemData.imagesUrl ??
"images/icon_video_placeholder.jpg")
.image),
),
),
Positioned(
left: 8.w,
bottom: 5.h,
child: Text(
formatString(state.videoController.value.duration),
style:
TextStyle(color: Colors.grey, fontSize: 20.sp))),
Visibility(
visible: isPlay,
child: Positioned(
left: 0,
right: 0,
top: 0,
bottom: 0,
child: Container(
// padding: EdgeInsets.only(right: 10.w, left: 10.w),
color: const Color.fromRGBO(0, 0, 0, 0.3),
child: Center(
child: Text("播放中",
style: TextStyle(
color: Colors.white, fontSize: 22.sp))),
)),
)
]),
),
SizedBox(height:5.h),
Text("2023.10.23 10:00", style: TextStyle(fontSize: 20.sp))
SizedBox(height: 5.h),
Text(
DateTool().dateToYMDHNString(itemData.operateDate.toString()),
style: TextStyle(fontSize: 18.sp))
],
),
],
@ -182,10 +215,14 @@ class _VideoLogDetailPageState extends State<VideoLogDetailPage> {
);
}
String formatString(time) {
var shortName = time.toString().substring(2, 7);
return shortName;
}
@override
void dispose() {
super.dispose();
_controller.dispose();
state.videoController.dispose();
}
}

View File

@ -1,5 +1,20 @@
import 'package:get/get.dart';
import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_entity.dart';
import 'package:video_player/video_player.dart';
class VideoLogDetailState {
var recordData = RecordListData().obs;
late VideoPlayerController videoController;
var videoLogList = [].obs;
class VideoLogDetailState{
VideoLogDetailState() {
Map map = Get.arguments;
if (map['recordData'] != null) {
recordData.value = map['recordData'];
}
}
if (map['videoDataList'] != null) {
videoLogList.value = map['videoDataList'];
}
}
}

View File

@ -12,6 +12,7 @@ import 'package:star_lock/main/lockDetail/messageWarn/msgNotification/coerceOpen
import 'package:star_lock/main/lockDetail/messageWarn/msgNotification/msgNotification/msgNotification_entity.dart';
import 'package:star_lock/main/lockDetail/passwordKey/passwordKeyList/passwordKeyListEntity.dart';
import 'package:star_lock/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKeyEntity.dart';
import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_entity.dart';
import 'package:star_lock/mine/mall/lockMall_entity.dart';
import 'package:star_lock/mine/minePersonInfo/minePersonInfoEditAccount/minePersonInfoEditAccount/mineUnbindPhoneOrEmail_entity.dart';
import 'package:star_lock/mine/minePersonInfo/minePersonInfoPage/minePersonInfo_entity.dart';
@ -1961,10 +1962,9 @@ class ApiRepository {
}
//
Future<CoerceFingerprintListEntity> getLockCloudStorageList(
{required int lockId}) async {
Future<VideoLogEntity> getLockCloudStorageList({required int lockId}) async {
final res = await apiProvider.getLockCloudStorageList(lockId);
return CoerceFingerprintListEntity.fromJson(res.body);
return VideoLogEntity.fromJson(res.body);
}
//

View File

@ -135,7 +135,7 @@ dependencies:
jpush_flutter: ^2.5.1
#视频播放器
video_player: ^2.7.1
video_player: ^2.8.5
#控制横竖屏控件
auto_orientation: ^2.3.1
audioplayers: ^5.2.1