From 0b749509730cfab6e46b6a2445f0805f05c6d627 Mon Sep 17 00:00:00 2001 From: ge59dil Date: Fri, 26 Jan 2024 09:56:54 +0100 Subject: [PATCH] Added video name and duration --- lib/models/download/download_state_model.dart | 31 ++++++++- lib/view_models/download_view_model.dart | 68 ++++++++++++++----- .../downloaded_courses_view.dart | 13 ++-- lib/views/video_view/video_player.dart | 2 +- 4 files changed, 89 insertions(+), 25 deletions(-) diff --git a/lib/models/download/download_state_model.dart b/lib/models/download/download_state_model.dart index cf45740a..11243ca3 100644 --- a/lib/models/download/download_state_model.dart +++ b/lib/models/download/download_state_model.dart @@ -2,17 +2,44 @@ import 'package:flutter/material.dart'; @immutable class DownloadState { - final Map downloadedVideos; + final Map downloadedVideos; const DownloadState({ this.downloadedVideos = const {}, }); DownloadState copyWith({ - Map? downloadedVideos, + Map? downloadedVideos, }) { return DownloadState( downloadedVideos: downloadedVideos ?? this.downloadedVideos, ); } } + +@immutable +class VideoDetails { + final String filePath; + final String name; + final int duration; // Duration in seconds or your preferred unit + + const VideoDetails({ + required this.filePath, + required this.name, + required this.duration, + }); + + VideoDetails copyWith({ + String? filePath, + String? name, + int? duration, + }) { + return VideoDetails( + filePath: filePath ?? this.filePath, + name: name ?? this.name, + duration: duration ?? this.duration, + ); + } + +// Implement toJson and fromJson if you need to serialize/deserialize the object +} diff --git a/lib/view_models/download_view_model.dart b/lib/view_models/download_view_model.dart index dfe86eef..9ef77c51 100644 --- a/lib/view_models/download_view_model.dart +++ b/lib/view_models/download_view_model.dart @@ -20,14 +20,23 @@ class DownloadViewModel extends StateNotifier { final jsonString = prefs.getString('downloadedVideos'); if (jsonString != null) { final downloaded = Map.from(json.decode(jsonString)); - final downloadedVideos = downloaded - .map((key, value) => MapEntry(int.parse(key), value.toString())); + final downloadedVideos = downloaded.map((key, value) { + // Decode the JSON string into a Map + final videoDetailsMap = json.decode(value); + // Create a VideoDetails object from the Map + final videoDetails = VideoDetails( + filePath: videoDetailsMap['filePath'], + name: videoDetailsMap['name'], + duration: videoDetailsMap['duration'], + ); + return MapEntry(int.parse(key), videoDetails); + }).cast(); // Ensure the map has the correct type state = state.copyWith(downloadedVideos: downloadedVideos); } } Future downloadVideo( - String videoUrl, Int64 streamId, String fileName,) async { + String videoUrl, Int64 streamId, String fileName, String streamName, int streamDuration,) async { try { final directory = await getApplicationDocumentsDirectory(); final filePath = '${directory.path}/$fileName'; @@ -37,14 +46,38 @@ class DownloadViewModel extends StateNotifier { final prefs = await SharedPreferences.getInstance(); final int streamIdInt = streamId.toInt(); - final downloadedVideos = Map.from(state.downloadedVideos) - ..[streamIdInt] = filePath; - // Save to SharedPreferences + // Create a map for the video details + final videoDetailsMap = { + 'filePath': filePath, + 'name': streamName, + 'duration': streamDuration, + }; + + // Convert video details map to JSON string + final videoDetailsJson = json.encode(videoDetailsMap); + + // Save the JSON string in your SharedPreferences + final downloadedVideosJson = Map.from(state.downloadedVideos) + ..[streamIdInt] = videoDetailsJson; + await prefs.setString( - 'downloadedVideos', - json.encode(downloadedVideos - .map((key, value) => MapEntry(key.toString(), value)),),); + 'downloadedVideos', + json.encode(downloadedVideosJson.map((key, value) => MapEntry(key.toString(), value))), + ); + + // Convert the JSON strings back to VideoDetails objects for the state + final downloadedVideos = downloadedVideosJson.map((key, value) { + final videoDetailsMap = json.decode(value); + final videoDetails = VideoDetails( + filePath: videoDetailsMap['filePath'], + name: videoDetailsMap['name'], + duration: videoDetailsMap['duration'], + ); + return MapEntry(key, videoDetails); + }).cast(); + + // Update the state state = state.copyWith(downloadedVideos: downloadedVideos); _logger.d('Downloaded videos: ${state.downloadedVideos}'); return filePath; @@ -61,34 +94,35 @@ class DownloadViewModel extends StateNotifier { _logger.e('Error fetching downloaded videos: $e'); } } - Future deleteDownload(int videoId) async { _logger.i('Deleting downloaded video with ID: $videoId'); try { - String? filePath = state.downloadedVideos[videoId]; - if (filePath != null && filePath.isNotEmpty) { + // Get the VideoDetails object from the state + VideoDetails? videoDetails = state.downloadedVideos[videoId]; + if (videoDetails != null) { + final filePath = videoDetails.filePath; final file = File(filePath); if (await file.exists()) { await file.delete(); _logger.d('Deleted video file at: $filePath'); final prefs = await SharedPreferences.getInstance(); - final updatedDownloads = - Map.from(state.downloadedVideos); + final updatedDownloads = Map.from(state.downloadedVideos); updatedDownloads.remove(videoId); // Save updated list to SharedPreferences + // Convert VideoDetails objects to JSON strings before saving await prefs.setString( 'downloadedVideos', - json.encode(updatedDownloads - .map((key, value) => MapEntry(key.toString(), value)),),); + json.encode(updatedDownloads.map((key, value) => MapEntry(key.toString(), json.encode(value)))) + ,); state = state.copyWith(downloadedVideos: updatedDownloads); } else { _logger.w('File not found: $filePath'); } } else { - _logger.w('No file path found for video ID: $videoId'); + _logger.w('No details found for video ID: $videoId'); } } catch (e) { _logger.e('Error deleting video with ID $videoId: $e'); diff --git a/lib/views/course_view/downloaded_courses_view/downloaded_courses_view.dart b/lib/views/course_view/downloaded_courses_view/downloaded_courses_view.dart index 462deb86..6ea78092 100644 --- a/lib/views/course_view/downloaded_courses_view/downloaded_courses_view.dart +++ b/lib/views/course_view/downloaded_courses_view/downloaded_courses_view.dart @@ -1,6 +1,6 @@ -import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:gocast_mobile/models/download/download_state_model.dart'; import 'package:gocast_mobile/providers.dart'; import 'package:gocast_mobile/views/components/custom_search_top_nav_bar.dart'; import 'package:gocast_mobile/views/course_view/downloaded_courses_view/download_card.dart'; @@ -42,14 +42,17 @@ class DownloadedCoursesState extends ConsumerState { ), videoCards: downloadedVideos.entries.map((entry) { final int videoId = entry.key; - final String localPath = entry.value; - + final VideoDetails videoDetails = entry.value; + final String localPath = videoDetails.filePath; + final String videoName = videoDetails.name; + final int durationSeconds = videoDetails.duration; + final String formattedDuration = "${(durationSeconds ~/ 3600).toString().padLeft(2, '0')}:${((durationSeconds % 3600) ~/ 60).toString().padLeft(2, '0')}:${(durationSeconds % 60).toString().padLeft(2, '0')}"; return VideoCard( duration: - "${Random().nextInt(2).toString().padLeft(2, '0')}:${Random().nextInt(59).toString().padLeft(2, '0')}:${Random().nextInt(60).toString().padLeft(2, '0')}", + formattedDuration, imageName: 'assets/images/course1.png', // Update as necessary - title: 'Video $videoId', + title: videoName, // Replace with the appropriate title date: 'Video Date', // Replace with the appropriate date diff --git a/lib/views/video_view/video_player.dart b/lib/views/video_view/video_player.dart index 57d3ce9b..483cfa21 100644 --- a/lib/views/video_view/video_player.dart +++ b/lib/views/video_view/video_player.dart @@ -262,7 +262,7 @@ class VideoPlayerPageState extends ConsumerState { // Call the download function from the StreamViewModel ref .read(downloadViewModelProvider.notifier) - .downloadVideo(downloadUrl, stream.id, fileName) + .downloadVideo(downloadUrl, stream.id, fileName,stream.name,stream.duration) .then((localPath) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Video Downloaded')),