diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index d915141a6..77ac42cf1 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -32,6 +32,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/ui/video_widget.dart b/lib/ui/video_widget.dart
index 0970eec31..c7dcaec17 100644
--- a/lib/ui/video_widget.dart
+++ b/lib/ui/video_widget.dart
@@ -43,6 +43,14 @@ class _VideoWidgetState extends State {
super.initState();
if (widget.file.isRemoteFile()) {
_loadNetworkVideo();
+ } else if (widget.file.isSharedMediaToAppSandbox()) {
+ final localFile = io.File(getSharedMediaFilePath(widget.file));
+ if (localFile.existsSync()) {
+ _logger.fine("loading from app cache");
+ _setVideoPlayerController(file: localFile);
+ } else if (widget.file.uploadedFileID != null) {
+ _loadNetworkVideo();
+ }
} else {
widget.file.getAsset().then((asset) async {
if (asset == null || !(await asset.exists)) {
@@ -62,12 +70,14 @@ class _VideoWidgetState extends State {
getFileFromServer(
widget.file,
progressCallback: (count, total) {
- setState(() {
- _progress = count / total;
- if (_progress == 1) {
- showToast("decrypting video...", toastLength: Toast.LENGTH_SHORT);
- }
- });
+ if (mounted) {
+ setState(() {
+ _progress = count / total;
+ if (_progress == 1) {
+ showToast("decrypting video...", toastLength: Toast.LENGTH_SHORT);
+ }
+ });
+ }
},
).then((file) {
if (file != null) {
diff --git a/lib/utils/file_uploader_util.dart b/lib/utils/file_uploader_util.dart
index 77b9c111c..8a5ed73da 100644
--- a/lib/utils/file_uploader_util.dart
+++ b/lib/utils/file_uploader_util.dart
@@ -6,6 +6,7 @@ import 'package:archive/archive_io.dart';
import 'package:logging/logging.dart';
import 'package:motionphoto/motionphoto.dart';
import 'package:path/path.dart';
+import 'package:path_provider/path_provider.dart';
import 'package:photo_manager/photo_manager.dart';
import 'package:photos/core/configuration.dart';
import 'package:photos/core/constants.dart';
@@ -13,6 +14,7 @@ import 'package:photos/core/errors.dart';
import 'package:photos/models/file.dart' as ente;
import 'package:photos/models/file_type.dart';
import 'package:photos/models/location.dart';
+import 'package:video_thumbnail/video_thumbnail.dart';
import 'file_util.dart';
@@ -140,8 +142,14 @@ Future _getMediaUploadDataFromAppCache(ente.File file) async {
_logger.warning("File doesn't exist in app sandbox");
throw InvalidFileError("File doesn't exist in app sandbox");
}
- thumbnailData = await getThumbnailFromInAppCacheFile(file);
- return MediaUploadData(sourceFile, thumbnailData, isDeleted);
+ try {
+ thumbnailData = await getThumbnailFromInAppCacheFile(file);
+ return MediaUploadData(sourceFile, thumbnailData, isDeleted);
+ } catch (e, s) {
+ _logger.severe("failed to generate thumbnail", e, s);
+ throw InvalidFileError(
+ "thumbnail generation failed for fileType: ${file.fileType.toString()}");
+ }
}
Future getThumbnailFromInAppCacheFile(ente.File file) async {
@@ -149,6 +157,16 @@ Future getThumbnailFromInAppCacheFile(ente.File file) async {
if (!localFile.existsSync()) {
return null;
}
+ if (file.fileType == FileType.video) {
+ final thumbnailFilePath = await VideoThumbnail.thumbnailFile(
+ video: localFile.path,
+ imageFormat: ImageFormat.JPEG,
+ thumbnailPath: (await getTemporaryDirectory()).path,
+ maxWidth: kThumbnailLargeSize,
+ quality: 80,
+ );
+ localFile = io.File(thumbnailFilePath);
+ }
var thumbnailData = await localFile.readAsBytes();
int compressionAttempts = 0;
while (thumbnailData.length > kThumbnailDataLimit &&
diff --git a/lib/utils/share_util.dart b/lib/utils/share_util.dart
index 33bfdd5bc..2bef1c831 100644
--- a/lib/utils/share_util.dart
+++ b/lib/utils/share_util.dart
@@ -40,29 +40,40 @@ Future> convertIncomingSharedMediaToFile(
List sharedMedia, int collectionID) async {
List localFiles = [];
for (var media in sharedMedia) {
+ if (!(media.type == SharedMediaType.IMAGE ||
+ media.type == SharedMediaType.VIDEO)) {
+ _logger.warning(
+ "ignore unsupported file type ${media.type.toString()} path: ${media.path}");
+ continue;
+ }
var enteFile = File();
// fileName: img_x.jpg
enteFile.title = basename(media.path);
-
var ioFile = dartio.File(media.path);
- ioFile = ioFile.renameSync(Configuration.instance.getSharedMediaCacheDirectory() +
- "/" +
- enteFile.title);
+ ioFile = ioFile.renameSync(
+ Configuration.instance.getSharedMediaCacheDirectory() +
+ "/" +
+ enteFile.title);
enteFile.localID = kSharedMediaIdentifier + enteFile.title;
enteFile.collectionID = collectionID;
- enteFile.fileType = FileType.image;
+ enteFile.fileType =
+ media.type == SharedMediaType.IMAGE ? FileType.image : FileType.video;
- var exifMap = await readExifFromFile(ioFile);
- if (exifMap != null &&
- exifMap["Image DateTime"] != null &&
- '0000:00:00 00:00:00' != exifMap["Image DateTime"].toString()) {
- try {
- final exifTime =
- _exifDateFormat.parse(exifMap["Image DateTime"].toString());
- enteFile.creationTime = exifTime.microsecondsSinceEpoch;
- } catch (e) {
- //ignore
+ if (enteFile.fileType == FileType.image) {
+ final exifMap = await readExifFromFile(ioFile);
+ if (exifMap != null &&
+ exifMap["Image DateTime"] != null &&
+ '0000:00:00 00:00:00' != exifMap["Image DateTime"].toString()) {
+ try {
+ final exifTime =
+ _exifDateFormat.parse(exifMap["Image DateTime"].toString());
+ enteFile.creationTime = exifTime.microsecondsSinceEpoch;
+ } catch (e) {
+ //ignore
+ }
}
+ } else if (enteFile.fileType == FileType.video) {
+ enteFile.duration = media.duration ?? 0;
}
if (enteFile.creationTime == null || enteFile.creationTime == 0) {
final parsedDateTime =
diff --git a/pubspec.lock b/pubspec.lock
index 81190bbe3..5325d50d6 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -1091,6 +1091,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
+ video_thumbnail:
+ dependency: "direct main"
+ description:
+ name: video_thumbnail
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.4.3"
visibility_detector:
dependency: "direct main"
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index b98ee16b2..b48b0d62d 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -98,6 +98,7 @@ dependencies:
url_launcher: ^6.0.3
uuid: ^3.0.4
video_player: ^2.0.0
+ video_thumbnail: ^0.4.3
visibility_detector: ^0.2.0
wallpaper_manager_flutter: ^0.0.2