Fix type mistmatch issues
This commit is contained in:
parent
6b5eea4d9e
commit
f81c92bfee
2 changed files with 50 additions and 47 deletions
|
@ -9,7 +9,6 @@ import 'package:photos/core/constants.dart';
|
||||||
import "package:photos/generated/l10n.dart";
|
import "package:photos/generated/l10n.dart";
|
||||||
import "package:photos/models/file/extensions/file_props.dart";
|
import "package:photos/models/file/extensions/file_props.dart";
|
||||||
import 'package:photos/models/file/file.dart';
|
import 'package:photos/models/file/file.dart';
|
||||||
import 'package:photos/models/file/file_type.dart';
|
|
||||||
import "package:photos/models/metadata/file_magic.dart";
|
import "package:photos/models/metadata/file_magic.dart";
|
||||||
import "package:photos/services/file_magic_service.dart";
|
import "package:photos/services/file_magic_service.dart";
|
||||||
import 'package:photos/ui/viewer/file/zoomable_image.dart';
|
import 'package:photos/ui/viewer/file/zoomable_image.dart';
|
||||||
|
@ -19,13 +18,13 @@ import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:video_player/video_player.dart';
|
import 'package:video_player/video_player.dart';
|
||||||
|
|
||||||
class ZoomableLiveImage extends StatefulWidget {
|
class ZoomableLiveImage extends StatefulWidget {
|
||||||
final EnteFile file;
|
final EnteFile enteFile;
|
||||||
final Function(bool)? shouldDisableScroll;
|
final Function(bool)? shouldDisableScroll;
|
||||||
final String? tagPrefix;
|
final String? tagPrefix;
|
||||||
final Decoration? backgroundDecoration;
|
final Decoration? backgroundDecoration;
|
||||||
|
|
||||||
const ZoomableLiveImage(
|
const ZoomableLiveImage(
|
||||||
this.file, {
|
this.enteFile, {
|
||||||
Key? key,
|
Key? key,
|
||||||
this.shouldDisableScroll,
|
this.shouldDisableScroll,
|
||||||
required this.tagPrefix,
|
required this.tagPrefix,
|
||||||
|
@ -39,7 +38,7 @@ class ZoomableLiveImage extends StatefulWidget {
|
||||||
class _ZoomableLiveImageState extends State<ZoomableLiveImage>
|
class _ZoomableLiveImageState extends State<ZoomableLiveImage>
|
||||||
with SingleTickerProviderStateMixin {
|
with SingleTickerProviderStateMixin {
|
||||||
final Logger _logger = Logger("ZoomableLiveImage");
|
final Logger _logger = Logger("ZoomableLiveImage");
|
||||||
late EnteFile _file;
|
late EnteFile _enteFile;
|
||||||
bool _showVideo = false;
|
bool _showVideo = false;
|
||||||
bool _isLoadingVideoPlayer = false;
|
bool _isLoadingVideoPlayer = false;
|
||||||
|
|
||||||
|
@ -48,7 +47,7 @@ class _ZoomableLiveImageState extends State<ZoomableLiveImage>
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
_file = widget.file;
|
_enteFile = widget.enteFile;
|
||||||
Future.microtask(() => _showHintForMotionPhotoPlay).ignore();
|
Future.microtask(() => _showHintForMotionPhotoPlay).ignore();
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
@ -77,7 +76,7 @@ class _ZoomableLiveImageState extends State<ZoomableLiveImage>
|
||||||
content = _getVideoPlayer();
|
content = _getVideoPlayer();
|
||||||
} else {
|
} else {
|
||||||
content = ZoomableImage(
|
content = ZoomableImage(
|
||||||
_file,
|
_enteFile,
|
||||||
tagPrefix: widget.tagPrefix,
|
tagPrefix: widget.tagPrefix,
|
||||||
shouldDisableScroll: widget.shouldDisableScroll,
|
shouldDisableScroll: widget.shouldDisableScroll,
|
||||||
backgroundDecoration: widget.backgroundDecoration,
|
backgroundDecoration: widget.backgroundDecoration,
|
||||||
|
@ -125,27 +124,30 @@ class _ZoomableLiveImageState extends State<ZoomableLiveImage>
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_isLoadingVideoPlayer = true;
|
_isLoadingVideoPlayer = true;
|
||||||
final File? videoFile = _file.fileType == FileType.livePhoto
|
// For non-live photo, with fileType as Image, we still call _getMotionPhoto
|
||||||
|
// to check if it is a motion photo. This is needed to handle earlier
|
||||||
|
// uploads and upload from desktop
|
||||||
|
final File? videoFile = _enteFile.isLivePhoto
|
||||||
? await _getLivePhotoVideo()
|
? await _getLivePhotoVideo()
|
||||||
: await _getMotionPhotoVideo();
|
: await _getMotionPhotoVideo();
|
||||||
|
|
||||||
if (videoFile != null && videoFile.existsSync()) {
|
if (videoFile != null && videoFile.existsSync()) {
|
||||||
_setVideoPlayerController(file: videoFile);
|
_setVideoPlayerController(file: videoFile);
|
||||||
} else if (_file.fileType == FileType.livePhoto) {
|
} else if (_enteFile.isLivePhoto) {
|
||||||
showShortToast(context, S.of(context).downloadFailed);
|
showShortToast(context, S.of(context).downloadFailed);
|
||||||
}
|
}
|
||||||
_isLoadingVideoPlayer = false;
|
_isLoadingVideoPlayer = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<File?> _getLivePhotoVideo() async {
|
Future<File?> _getLivePhotoVideo() async {
|
||||||
if (_file.isRemoteFile && !(await isFileCached(_file, liveVideo: true))) {
|
if (_enteFile.isRemoteFile && !(await isFileCached(_enteFile, liveVideo: true))) {
|
||||||
showShortToast(context, S.of(context).downloading);
|
showShortToast(context, S.of(context).downloading);
|
||||||
}
|
}
|
||||||
|
|
||||||
File? videoFile = await getFile(widget.file, liveVideo: true)
|
File? videoFile = await getFile(widget.enteFile, liveVideo: true)
|
||||||
.timeout(const Duration(seconds: 15))
|
.timeout(const Duration(seconds: 15))
|
||||||
.onError((dynamic e, s) {
|
.onError((dynamic e, s) {
|
||||||
_logger.info("getFile failed ${_file.tag}", e);
|
_logger.info("getFile failed ${_enteFile.tag}", e);
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -153,11 +155,11 @@ class _ZoomableLiveImageState extends State<ZoomableLiveImage>
|
||||||
// getFile with liveVideo as true can fail for file with localID when
|
// getFile with liveVideo as true can fail for file with localID when
|
||||||
// the live photo was downloaded from remote.
|
// the live photo was downloaded from remote.
|
||||||
if ((videoFile == null || !videoFile.existsSync()) &&
|
if ((videoFile == null || !videoFile.existsSync()) &&
|
||||||
_file.uploadedFileID != null) {
|
_enteFile.uploadedFileID != null) {
|
||||||
videoFile = await getFileFromServer(widget.file, liveVideo: true)
|
videoFile = await getFileFromServer(widget.enteFile, liveVideo: true)
|
||||||
.timeout(const Duration(seconds: 15))
|
.timeout(const Duration(seconds: 15))
|
||||||
.onError((dynamic e, s) {
|
.onError((dynamic e, s) {
|
||||||
_logger.info("getRemoteFile failed ${_file.tag}", e);
|
_logger.info("getRemoteFile failed ${_enteFile.tag}", e);
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -165,25 +167,25 @@ class _ZoomableLiveImageState extends State<ZoomableLiveImage>
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<File?> _getMotionPhotoVideo() async {
|
Future<File?> _getMotionPhotoVideo() async {
|
||||||
if (_file.isRemoteFile && !(await isFileCached(_file))) {
|
if (_enteFile.isRemoteFile && !(await isFileCached(_enteFile))) {
|
||||||
showShortToast(context, S.of(context).downloading);
|
showShortToast(context, S.of(context).downloading);
|
||||||
}
|
}
|
||||||
|
|
||||||
final File? imageFile = await getFile(
|
final File? imageFile = await getFile(
|
||||||
widget.file,
|
widget.enteFile,
|
||||||
isOrigin: !Platform.isAndroid,
|
isOrigin: !Platform.isAndroid,
|
||||||
).timeout(const Duration(seconds: 15)).onError((dynamic e, s) {
|
).timeout(const Duration(seconds: 15)).onError((dynamic e, s) {
|
||||||
_logger.info("getFile failed ${_file.tag}", e);
|
_logger.info("getFile failed ${_enteFile.tag}", e);
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
if (imageFile != null) {
|
if (imageFile != null) {
|
||||||
final motionPhoto = MotionPhotos(imageFile.path);
|
final motionPhoto = MotionPhotos(imageFile.path);
|
||||||
final index = await motionPhoto.getMotionVideoIndex();
|
final index = await motionPhoto.getMotionVideoIndex();
|
||||||
if (index != null) {
|
if (index != null) {
|
||||||
if (widget.file.pubMagicMetadata?.mvi == null &&
|
if (widget.enteFile.pubMagicMetadata?.mvi == null &&
|
||||||
(widget.file.ownerID ?? 0) == Configuration.instance.getUserID()!) {
|
(widget.enteFile.ownerID ?? 0) == Configuration.instance.getUserID()!) {
|
||||||
FileMagicService.instance.updatePublicMagicMetadata(
|
FileMagicService.instance.updatePublicMagicMetadata(
|
||||||
[widget.file],
|
[widget.enteFile],
|
||||||
{motionVideoIndexKey: index.start},
|
{motionVideoIndexKey: index.start},
|
||||||
).ignore();
|
).ignore();
|
||||||
}
|
}
|
||||||
|
@ -209,7 +211,7 @@ class _ZoomableLiveImageState extends State<ZoomableLiveImage>
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showHintForMotionPhotoPlay() async {
|
void _showHintForMotionPhotoPlay() async {
|
||||||
if (!_file.isLiveOrMotionPhoto) {
|
if (!_enteFile.isLiveOrMotionPhoto) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final preferences = await SharedPreferences.getInstance();
|
final preferences = await SharedPreferences.getInstance();
|
||||||
|
|
|
@ -49,7 +49,8 @@ class FileUploader {
|
||||||
final _logger = Logger("FileUploader");
|
final _logger = Logger("FileUploader");
|
||||||
final _dio = NetworkClient.instance.getDio();
|
final _dio = NetworkClient.instance.getDio();
|
||||||
final _enteDio = NetworkClient.instance.enteDio;
|
final _enteDio = NetworkClient.instance.enteDio;
|
||||||
final LinkedHashMap _queue = LinkedHashMap<String, FileUploadItem>();
|
final LinkedHashMap<String, FileUploadItem> _queue =
|
||||||
|
LinkedHashMap<String, FileUploadItem>();
|
||||||
final _uploadLocks = UploadLocksDB.instance;
|
final _uploadLocks = UploadLocksDB.instance;
|
||||||
final kSafeBufferForLockExpiry = const Duration(days: 1).inMicroseconds;
|
final kSafeBufferForLockExpiry = const Duration(days: 1).inMicroseconds;
|
||||||
final kBGTaskDeathTimeout = const Duration(seconds: 5).inMicroseconds;
|
final kBGTaskDeathTimeout = const Duration(seconds: 5).inMicroseconds;
|
||||||
|
@ -126,18 +127,18 @@ class FileUploader {
|
||||||
if (file.localID == null || file.localID!.isEmpty) {
|
if (file.localID == null || file.localID!.isEmpty) {
|
||||||
return Future.error(Exception("file's localID can not be null or empty"));
|
return Future.error(Exception("file's localID can not be null or empty"));
|
||||||
}
|
}
|
||||||
// If the file hasn't been queued yet, queue it
|
// If the file hasn't been queued yet, queue it for upload
|
||||||
_totalCountInUploadSession++;
|
_totalCountInUploadSession++;
|
||||||
if (!_queue.containsKey(file.localID)) {
|
final String localID = file.localID!;
|
||||||
|
if (!_queue.containsKey(localID)) {
|
||||||
final completer = Completer<EnteFile>();
|
final completer = Completer<EnteFile>();
|
||||||
_queue[file.localID] = FileUploadItem(file, collectionID, completer);
|
_queue[localID] = FileUploadItem(file, collectionID, completer);
|
||||||
_pollQueue();
|
_pollQueue();
|
||||||
return completer.future;
|
return completer.future;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the file exists in the queue for a matching collectionID,
|
// If the file exists in the queue for a matching collectionID,
|
||||||
// return the existing future
|
// return the existing future
|
||||||
final item = _queue[file.localID];
|
final FileUploadItem item = _queue[localID]!;
|
||||||
if (item.collectionID == collectionID) {
|
if (item.collectionID == collectionID) {
|
||||||
_totalCountInUploadSession--;
|
_totalCountInUploadSession--;
|
||||||
return item.completer.future;
|
return item.completer.future;
|
||||||
|
@ -154,16 +155,16 @@ class FileUploader {
|
||||||
"original upload completer resolved, try adding the file to another "
|
"original upload completer resolved, try adding the file to another "
|
||||||
"collection",
|
"collection",
|
||||||
);
|
);
|
||||||
if (uploadedFile == null) {
|
// if (uploadedFile == null) {
|
||||||
/* todo: handle this case, ideally during next sync the localId
|
// /* todo: handle this case, ideally during next sync the localId
|
||||||
should be uploaded to this collection ID
|
// should be uploaded to this collection ID
|
||||||
*/
|
// */
|
||||||
_logger.severe('unexpected upload state');
|
// _logger.severe('unexpected upload state');
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
return CollectionsService.instance
|
return CollectionsService.instance
|
||||||
.addToCollection(collectionID, [uploadedFile]).then((aVoid) {
|
.addToCollection(collectionID, [uploadedFile]).then((aVoid) {
|
||||||
return uploadedFile as EnteFile;
|
return uploadedFile;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -180,7 +181,7 @@ class FileUploader {
|
||||||
uploadsToBeRemoved.add(pendingUpload.key);
|
uploadsToBeRemoved.add(pendingUpload.key);
|
||||||
});
|
});
|
||||||
for (final id in uploadsToBeRemoved) {
|
for (final id in uploadsToBeRemoved) {
|
||||||
_queue.remove(id).completer.completeError(reason);
|
_queue.remove(id)?.completer.completeError(reason);
|
||||||
}
|
}
|
||||||
_totalCountInUploadSession = 0;
|
_totalCountInUploadSession = 0;
|
||||||
}
|
}
|
||||||
|
@ -202,7 +203,7 @@ class FileUploader {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
for (final id in uploadsToBeRemoved) {
|
for (final id in uploadsToBeRemoved) {
|
||||||
_queue.remove(id).completer.completeError(reason);
|
_queue.remove(id)?.completer.completeError(reason);
|
||||||
}
|
}
|
||||||
_logger.info(
|
_logger.info(
|
||||||
'number of enteries removed from queue ${uploadsToBeRemoved.length}',
|
'number of enteries removed from queue ${uploadsToBeRemoved.length}',
|
||||||
|
@ -257,7 +258,7 @@ class FileUploader {
|
||||||
if (file.fileType == FileType.video) {
|
if (file.fileType == FileType.video) {
|
||||||
_videoUploadCounter++;
|
_videoUploadCounter++;
|
||||||
}
|
}
|
||||||
final localID = file.localID;
|
final localID = file.localID!;
|
||||||
try {
|
try {
|
||||||
final uploadedFile =
|
final uploadedFile =
|
||||||
await _tryToUpload(file, collectionID, forcedUpload).timeout(
|
await _tryToUpload(file, collectionID, forcedUpload).timeout(
|
||||||
|
@ -268,14 +269,14 @@ class FileUploader {
|
||||||
throw TimeoutException(message);
|
throw TimeoutException(message);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
_queue.remove(localID).completer.complete(uploadedFile);
|
_queue.remove(localID)!.completer.complete(uploadedFile);
|
||||||
return uploadedFile;
|
return uploadedFile;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e is LockAlreadyAcquiredError) {
|
if (e is LockAlreadyAcquiredError) {
|
||||||
_queue[localID].status = UploadStatus.inBackground;
|
_queue[localID]!.status = UploadStatus.inBackground;
|
||||||
return _queue[localID].completer.future;
|
return _queue[localID]!.completer.future;
|
||||||
} else {
|
} else {
|
||||||
_queue.remove(localID).completer.completeError(e);
|
_queue.remove(localID)!.completer.completeError(e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -1028,19 +1029,19 @@ class FileUploader {
|
||||||
for (final upload in blockedUploads) {
|
for (final upload in blockedUploads) {
|
||||||
final file = upload.value.file;
|
final file = upload.value.file;
|
||||||
final isStillLocked = await _uploadLocks.isLocked(
|
final isStillLocked = await _uploadLocks.isLocked(
|
||||||
file.localID,
|
file.localID!,
|
||||||
ProcessType.background.toString(),
|
ProcessType.background.toString(),
|
||||||
);
|
);
|
||||||
if (!isStillLocked) {
|
if (!isStillLocked) {
|
||||||
final completer = _queue.remove(upload.key).completer;
|
final completer = _queue.remove(upload.key)?.completer;
|
||||||
final dbFile =
|
final dbFile =
|
||||||
await FilesDB.instance.getFile(upload.value.file.generatedID);
|
await FilesDB.instance.getFile(upload.value.file.generatedID!);
|
||||||
if (dbFile?.uploadedFileID != null) {
|
if (dbFile?.uploadedFileID != null) {
|
||||||
_logger.info("Background upload success detected");
|
_logger.info("Background upload success detected");
|
||||||
completer.complete(dbFile);
|
completer?.complete(dbFile);
|
||||||
} else {
|
} else {
|
||||||
_logger.info("Background upload failure detected");
|
_logger.info("Background upload failure detected");
|
||||||
completer.completeError(SilentlyCancelUploadsError());
|
completer?.completeError(SilentlyCancelUploadsError());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue