Merge branch 'main' into prepare_for_release_v0.8.73
This commit is contained in:
commit
bc0a453cbc
7 changed files with 128 additions and 19 deletions
|
@ -79,3 +79,5 @@ class LoginKeyDerivationError extends Error {}
|
|||
class SrpSetupNotCompleteError extends Error {}
|
||||
|
||||
class SharingNotPermittedForFreeAccountsError extends Error {}
|
||||
|
||||
class NoMediaLocationAccessError extends Error {}
|
||||
|
|
|
@ -170,7 +170,8 @@ class RemoteSyncService {
|
|||
e is NoActiveSubscriptionError ||
|
||||
e is WiFiUnavailableError ||
|
||||
e is StorageLimitExceededError ||
|
||||
e is SyncStopRequestedError) {
|
||||
e is SyncStopRequestedError ||
|
||||
e is NoMediaLocationAccessError) {
|
||||
_logger.warning("Error executing remote sync", e, s);
|
||||
rethrow;
|
||||
} else {
|
||||
|
@ -555,6 +556,7 @@ class RemoteSyncService {
|
|||
final int toBeUploaded = filesToBeUploaded.length + updatedFileIDs.length;
|
||||
if (toBeUploaded > 0) {
|
||||
Bus.instance.fire(SyncStatusUpdate(SyncStatus.preparingForUpload));
|
||||
await _uploader.verifyMediaLocationAccess();
|
||||
await _uploader.checkNetworkForUpload();
|
||||
// verify if files upload is allowed based on their subscription plan and
|
||||
// storage limit. To avoid creating new endpoint, we are using
|
||||
|
|
|
@ -120,6 +120,14 @@ class SyncService {
|
|||
} on UnauthorizedError {
|
||||
_logger.info("Logging user out");
|
||||
Bus.instance.fire(TriggerLogoutEvent());
|
||||
} on NoMediaLocationAccessError {
|
||||
_logger.severe("Not uploading due to no media location access");
|
||||
Bus.instance.fire(
|
||||
SyncStatusUpdate(
|
||||
SyncStatus.error,
|
||||
error: NoMediaLocationAccessError(),
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
if (e is DioError) {
|
||||
if (e.type == DioErrorType.connectTimeout ||
|
||||
|
|
|
@ -3,6 +3,7 @@ import 'dart:io';
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import "package:flutter_image_compress/flutter_image_compress.dart";
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:photo_view/photo_view.dart';
|
||||
import 'package:photos/core/cache/thumbnail_in_memory_cache.dart';
|
||||
|
@ -50,6 +51,7 @@ class _ZoomableImageState extends State<ZoomableImage> {
|
|||
bool _loadedLargeThumbnail = false;
|
||||
bool _loadingFinalImage = false;
|
||||
bool _loadedFinalImage = false;
|
||||
bool _convertToSupportedFormat = false;
|
||||
ValueChanged<PhotoViewScaleState>? _scaleStateChangedCallback;
|
||||
bool _isZooming = false;
|
||||
PhotoViewController _photoViewController = PhotoViewController();
|
||||
|
@ -194,11 +196,8 @@ class _ZoomableImageState extends State<ZoomableImage> {
|
|||
_loadingFinalImage = true;
|
||||
getFileFromServer(_photo).then((file) {
|
||||
if (file != null) {
|
||||
_onFinalImageLoaded(
|
||||
Image.file(
|
||||
file,
|
||||
gaplessPlayback: true,
|
||||
).image,
|
||||
_onFileLoaded(
|
||||
file,
|
||||
);
|
||||
} else {
|
||||
_loadingFinalImage = false;
|
||||
|
@ -239,7 +238,9 @@ class _ZoomableImageState extends State<ZoomableImage> {
|
|||
_isGIF(), // since on iOS GIFs playback only when origin-files are loaded
|
||||
).then((file) {
|
||||
if (file != null && file.existsSync()) {
|
||||
_onFinalImageLoaded(Image.file(file).image);
|
||||
_onFileLoaded(
|
||||
file,
|
||||
);
|
||||
} else {
|
||||
_logger.info("File was deleted " + _photo.toString());
|
||||
if (_photo.uploadedFileID != null) {
|
||||
|
@ -277,24 +278,45 @@ class _ZoomableImageState extends State<ZoomableImage> {
|
|||
}
|
||||
}
|
||||
|
||||
void _onFinalImageLoaded(ImageProvider imageProvider) {
|
||||
void _onFileLoaded(File file) {
|
||||
final imageProvider = Image.file(
|
||||
file,
|
||||
gaplessPlayback: true,
|
||||
).image;
|
||||
|
||||
if (mounted) {
|
||||
precacheImage(imageProvider, context).then((value) async {
|
||||
if (mounted) {
|
||||
await _updatePhotoViewController(
|
||||
previewImageProvider: _imageProvider,
|
||||
finalImageProvider: imageProvider,
|
||||
);
|
||||
setState(() {
|
||||
_imageProvider = imageProvider;
|
||||
_loadedFinalImage = true;
|
||||
_logger.info("Final image loaded");
|
||||
});
|
||||
precacheImage(
|
||||
imageProvider,
|
||||
context,
|
||||
onError: (exception, _) async {
|
||||
_logger
|
||||
.info(exception.toString() + ". Filename: ${_photo.displayName}");
|
||||
if (exception.toString().contains(
|
||||
"Codec failed to produce an image, possibly due to invalid image data",
|
||||
)) {
|
||||
unawaited(_loadInSupportedFormat(file));
|
||||
}
|
||||
},
|
||||
).then((value) {
|
||||
if (mounted && !_loadedFinalImage && !_convertToSupportedFormat) {
|
||||
_updateViewWithFinalImage(imageProvider);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _updateViewWithFinalImage(ImageProvider imageProvider) async {
|
||||
await _updatePhotoViewController(
|
||||
previewImageProvider: _imageProvider,
|
||||
finalImageProvider: imageProvider,
|
||||
);
|
||||
setState(() {
|
||||
_imageProvider = imageProvider;
|
||||
_loadedFinalImage = true;
|
||||
_logger.info("Final image loaded");
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _updatePhotoViewController({
|
||||
required ImageProvider? previewImageProvider,
|
||||
required ImageProvider finalImageProvider,
|
||||
|
@ -348,4 +370,28 @@ class _ZoomableImageState extends State<ZoomableImage> {
|
|||
}
|
||||
|
||||
bool _isGIF() => _photo.displayName.toLowerCase().endsWith(".gif");
|
||||
|
||||
Future<void> _loadInSupportedFormat(File file) async {
|
||||
_logger.info("Compressing ${_photo.displayName} to viewable format");
|
||||
_convertToSupportedFormat = true;
|
||||
|
||||
final compressedFile =
|
||||
await FlutterImageCompress.compressWithFile(file.path);
|
||||
|
||||
if (compressedFile != null) {
|
||||
final imageProvider = MemoryImage(compressedFile);
|
||||
|
||||
unawaited(
|
||||
precacheImage(imageProvider, context).then((value) {
|
||||
if (mounted) {
|
||||
_updateViewWithFinalImage(imageProvider);
|
||||
}
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
_logger.severe(
|
||||
"Failed to compress image ${_photo.displayName} to viewable format",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import 'package:connectivity_plus/connectivity_plus.dart';
|
|||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import "package:permission_handler/permission_handler.dart";
|
||||
import 'package:photos/core/configuration.dart';
|
||||
import "package:photos/core/constants.dart";
|
||||
import 'package:photos/core/errors.dart';
|
||||
|
@ -363,6 +364,15 @@ class FileUploader {
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> verifyMediaLocationAccess() async {
|
||||
if (Platform.isAndroid) {
|
||||
final bool hasPermission = await Permission.accessMediaLocation.isGranted;
|
||||
if (!hasPermission) {
|
||||
throw NoMediaLocationAccessError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<EnteFile> forceUpload(EnteFile file, int collectionID) async {
|
||||
_hasInitiatedForceUpload = true;
|
||||
return _tryToUpload(file, collectionID, true);
|
||||
|
|
|
@ -1538,6 +1538,46 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.1"
|
||||
permission_handler:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: permission_handler
|
||||
sha256: "284a66179cabdf942f838543e10413246f06424d960c92ba95c84439154fcac8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "11.0.1"
|
||||
permission_handler_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_android
|
||||
sha256: f9fddd3b46109bd69ff3f9efa5006d2d309b7aec0f3c1c5637a60a2d5659e76e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "11.1.0"
|
||||
permission_handler_apple:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_apple
|
||||
sha256: "99e220bce3f8877c78e4ace901082fb29fa1b4ebde529ad0932d8d664b34f3f5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.1.4"
|
||||
permission_handler_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_platform_interface
|
||||
sha256: "6760eb5ef34589224771010805bea6054ad28453906936f843a8cc4d3a55c4a4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.12.0"
|
||||
permission_handler_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_windows
|
||||
sha256: cc074aace208760f1eee6aa4fae766b45d947df85bc831cde77009cdb4720098
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.3"
|
||||
petitparser:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -130,6 +130,7 @@ dependencies:
|
|||
path: #dart
|
||||
path_provider: ^2.1.1
|
||||
pedantic: ^1.9.2
|
||||
permission_handler: ^11.0.1
|
||||
photo_manager: ^2.8.1
|
||||
photo_view: ^0.14.0
|
||||
pinput: ^1.2.2
|
||||
|
|
Loading…
Add table
Reference in a new issue