Merge branch 'main' into pull_down_fix
This commit is contained in:
commit
9e75d4c4d2
50 changed files with 382 additions and 149 deletions
|
@ -61,7 +61,7 @@ analyzer:
|
|||
cancel_subscriptions: error
|
||||
|
||||
|
||||
unawaited_futures: ignore # convert to warning after fixing existing issues
|
||||
unawaited_futures: warning # convert to warning after fixing existing issues
|
||||
invalid_dependency: info
|
||||
use_build_context_synchronously: ignore # experimental lint, requires many changes
|
||||
prefer_interpolation_to_compose_strings: ignore # later too many warnings
|
||||
|
|
|
@ -171,7 +171,7 @@ class Configuration {
|
|||
SearchService.instance.clearCache();
|
||||
Bus.instance.fire(UserLoggedOutEvent());
|
||||
} else {
|
||||
_preferences.setBool("auto_logout", true);
|
||||
await _preferences.setBool("auto_logout", true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -171,7 +171,7 @@ class SuperLogging {
|
|||
await setupLogDir();
|
||||
}
|
||||
if (sentryIsEnabled) {
|
||||
setupSentry();
|
||||
setupSentry().ignore();
|
||||
}
|
||||
|
||||
Logger.root.level = Level.ALL;
|
||||
|
@ -266,7 +266,7 @@ class SuperLogging {
|
|||
|
||||
// add error to sentry queue
|
||||
if (sentryIsEnabled && rec.error != null) {
|
||||
_sendErrorToSentry(rec.error!, null);
|
||||
_sendErrorToSentry(rec.error!, null).ignore();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -303,7 +303,7 @@ class SuperLogging {
|
|||
static Future<void> setupSentry() async {
|
||||
await for (final error in sentryQueueControl.stream.asBroadcastStream()) {
|
||||
try {
|
||||
Sentry.captureException(
|
||||
await Sentry.captureException(
|
||||
error,
|
||||
);
|
||||
} catch (e) {
|
||||
|
|
|
@ -14,6 +14,7 @@ class FileUpdationDB {
|
|||
static const tableName = 're_upload_tracker';
|
||||
static const columnLocalID = 'local_id';
|
||||
static const columnReason = 'reason';
|
||||
static const livePhotoSize = 'livePhotoSize';
|
||||
|
||||
static const modificationTimeUpdated = 'modificationTimeUpdated';
|
||||
|
||||
|
|
|
@ -1449,6 +1449,28 @@ class FilesDB {
|
|||
return result;
|
||||
}
|
||||
|
||||
// For a given userID, return unique uploadedFileId for the given userID
|
||||
Future<List<String>> getLivePhotosWithBadSize(
|
||||
int userId,
|
||||
int sizeInBytes,
|
||||
) async {
|
||||
final db = await instance.database;
|
||||
final rows = await db.query(
|
||||
filesTable,
|
||||
columns: [columnLocalID],
|
||||
distinct: true,
|
||||
where: '$columnOwnerID = ? AND '
|
||||
'($columnFileSize IS NULL OR $columnFileSize = ?) AND '
|
||||
'$columnFileType = ? AND $columnLocalID IS NOT NULL',
|
||||
whereArgs: [userId, sizeInBytes, getInt(FileType.livePhoto)],
|
||||
);
|
||||
final result = <String>[];
|
||||
for (final row in rows) {
|
||||
result.add(row[columnLocalID] as String);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// updateSizeForUploadIDs takes a map of upploadedFileID and fileSize and
|
||||
// update the fileSize for the given uploadedFileID
|
||||
Future<void> updateSizeForUploadIDs(
|
||||
|
|
|
@ -65,8 +65,8 @@ void main() async {
|
|||
MediaKit.ensureInitialized();
|
||||
final savedThemeMode = await AdaptiveTheme.getThemeMode();
|
||||
await _runInForeground(savedThemeMode);
|
||||
BackgroundFetch.registerHeadlessTask(_headlessTaskHandler);
|
||||
FlutterDisplayMode.setHighRefreshRate();
|
||||
unawaited(BackgroundFetch.registerHeadlessTask(_headlessTaskHandler));
|
||||
FlutterDisplayMode.setHighRefreshRate().ignore();
|
||||
}
|
||||
|
||||
Future<void> _runInForeground(AdaptiveThemeMode? savedThemeMode) async {
|
||||
|
@ -129,7 +129,7 @@ Future<void> _runInBackground(String taskId) async {
|
|||
_scheduleSuicide(kBGTaskTimeout, taskId); // To prevent OS from punishing us
|
||||
}
|
||||
await _init(true, via: 'runViaBackgroundTask');
|
||||
UpdateService.instance.showUpdateNotification();
|
||||
UpdateService.instance.showUpdateNotification().ignore();
|
||||
await _sync('bgSync');
|
||||
BackgroundFetch.finish(taskId);
|
||||
}
|
||||
|
@ -158,7 +158,7 @@ Future<void> _init(bool isBackground, {String via = ''}) async {
|
|||
AppLifecycleService.instance.onAppInForeground('init via: $via');
|
||||
}
|
||||
// Start workers asynchronously. No need to wait for them to start
|
||||
Computer.shared().turnOn(workersCount: 4, verbose: kDebugMode);
|
||||
Computer.shared().turnOn(workersCount: 4, verbose: kDebugMode).ignore();
|
||||
CryptoUtil.init();
|
||||
await NetworkClient.instance.init();
|
||||
await Configuration.instance.init();
|
||||
|
|
|
@ -181,7 +181,7 @@ extension SectionTypeExtensions on SectionType {
|
|||
switch (this) {
|
||||
case SectionType.contacts:
|
||||
return () async {
|
||||
shareText(
|
||||
await shareText(
|
||||
S.of(context).shareTextRecommendUsingEnte,
|
||||
);
|
||||
};
|
||||
|
@ -210,7 +210,7 @@ extension SectionTypeExtensions on SectionType {
|
|||
try {
|
||||
final Collection c =
|
||||
await CollectionsService.instance.createAlbum(text);
|
||||
routeToPage(
|
||||
await routeToPage(
|
||||
context,
|
||||
CollectionPage(CollectionWithThumbnail(c, null)),
|
||||
);
|
||||
|
@ -222,7 +222,7 @@ extension SectionTypeExtensions on SectionType {
|
|||
},
|
||||
);
|
||||
if (result is Exception) {
|
||||
showGenericErrorDialog(context: context, error: result);
|
||||
await showGenericErrorDialog(context: context, error: result);
|
||||
}
|
||||
};
|
||||
default:
|
||||
|
|
|
@ -184,7 +184,7 @@ class BillingService {
|
|||
try {
|
||||
final String jwtToken = await UserService.instance.getFamiliesToken();
|
||||
final bool familyExist = userDetails.isPartOfFamily();
|
||||
Navigator.of(context).push(
|
||||
await Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
return WebPage(
|
||||
|
@ -196,7 +196,7 @@ class BillingService {
|
|||
);
|
||||
} catch (e) {
|
||||
await dialog.hide();
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
}
|
||||
await dialog.hide();
|
||||
}
|
||||
|
|
|
@ -163,7 +163,7 @@ class EntityService {
|
|||
encryptedKey = response.encryptedKey;
|
||||
header = response.header;
|
||||
await _prefs.setString(_getEntityKeyPrefix(type), encryptedKey);
|
||||
_prefs.setString(_getEntityHeaderPrefix(type), header);
|
||||
await _prefs.setString(_getEntityHeaderPrefix(type), header);
|
||||
}
|
||||
final entityKey = CryptoUtil.decryptSync(
|
||||
Sodium.base642bin(encryptedKey),
|
||||
|
|
|
@ -49,11 +49,7 @@ class FilesService {
|
|||
if (uploadIDsWithMissingSize.isEmpty) {
|
||||
return Future.value(true);
|
||||
}
|
||||
final batchedFiles = uploadIDsWithMissingSize.chunks(1000);
|
||||
for (final batch in batchedFiles) {
|
||||
final Map<int, int> uploadIdToSize = await getFilesSizeFromInfo(batch);
|
||||
await _filesDB.updateSizeForUploadIDs(uploadIdToSize);
|
||||
}
|
||||
await backFillSizes(uploadIDsWithMissingSize);
|
||||
return Future.value(true);
|
||||
} catch (e, s) {
|
||||
_logger.severe("error during has migrated sizes", e, s);
|
||||
|
@ -61,6 +57,14 @@ class FilesService {
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> backFillSizes(List<int> uploadIDsWithMissingSize) async {
|
||||
final batchedFiles = uploadIDsWithMissingSize.chunks(1000);
|
||||
for (final batch in batchedFiles) {
|
||||
final Map<int, int> uploadIdToSize = await getFilesSizeFromInfo(batch);
|
||||
await _filesDB.updateSizeForUploadIDs(uploadIdToSize);
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map<int, int>> getFilesSizeFromInfo(List<int> uploadedFileID) async {
|
||||
try {
|
||||
final response = await _enteDio.post(
|
||||
|
|
|
@ -154,7 +154,7 @@ extension HiddenService on CollectionsService {
|
|||
} catch (e, s) {
|
||||
_logger.severe("Could not hide", e, s);
|
||||
await dialog.hide();
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
return false;
|
||||
} finally {
|
||||
await dialog.hide();
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import "dart:async";
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:local_auth/local_auth.dart';
|
||||
import 'package:photos/core/configuration.dart';
|
||||
|
@ -22,7 +24,7 @@ class LocalAuthenticationService {
|
|||
Configuration.instance.shouldShowLockScreen(),
|
||||
);
|
||||
if (!result) {
|
||||
showToast(context, infoMessage);
|
||||
unawaited(showToast(context, infoMessage));
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
|
@ -54,10 +56,12 @@ class LocalAuthenticationService {
|
|||
.setEnabled(Configuration.instance.shouldShowLockScreen());
|
||||
}
|
||||
} else {
|
||||
showErrorDialog(
|
||||
context,
|
||||
errorDialogTitle,
|
||||
errorDialogContent,
|
||||
unawaited(
|
||||
showErrorDialog(
|
||||
context,
|
||||
errorDialogTitle,
|
||||
errorDialogContent,
|
||||
),
|
||||
);
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -7,8 +7,10 @@ import "package:photos/core/configuration.dart";
|
|||
import 'package:photos/core/errors.dart';
|
||||
import 'package:photos/db/file_updation_db.dart';
|
||||
import 'package:photos/db/files_db.dart';
|
||||
import "package:photos/extensions/stop_watch.dart";
|
||||
import 'package:photos/models/file/file.dart';
|
||||
import 'package:photos/models/file/file_type.dart';
|
||||
import "package:photos/services/files_service.dart";
|
||||
import 'package:photos/utils/file_uploader_util.dart';
|
||||
import 'package:photos/utils/file_util.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
@ -19,6 +21,9 @@ class LocalFileUpdateService {
|
|||
late FileUpdationDB _fileUpdationDB;
|
||||
late SharedPreferences _prefs;
|
||||
late Logger _logger;
|
||||
final String _iosLivePhotoSizeMigrationDone = 'fm_ios_live_photo_size';
|
||||
final String _doneLivePhotoImport = 'fm_import_ios_live_photo_size';
|
||||
static int fourMBWithChunkSize = 4194338;
|
||||
final List<String> _oldMigrationKeys = [
|
||||
'fm_badCreationTime',
|
||||
'fm_badCreationTimeCompleted',
|
||||
|
@ -52,6 +57,8 @@ class LocalFileUpdateService {
|
|||
await _markFilesWhichAreActuallyUpdated();
|
||||
if (Platform.isAndroid) {
|
||||
_cleanUpOlderMigration().ignore();
|
||||
} else {
|
||||
await _handleLivePhotosSizedCheck();
|
||||
}
|
||||
} catch (e, s) {
|
||||
_logger.severe('failed to perform migration', e, s);
|
||||
|
@ -199,6 +206,146 @@ class LocalFileUpdateService {
|
|||
);
|
||||
}
|
||||
|
||||
Future<void> _handleLivePhotosSizedCheck() async {
|
||||
try {
|
||||
if (_prefs.containsKey(_iosLivePhotoSizeMigrationDone)) {
|
||||
return;
|
||||
}
|
||||
await _importLivePhotoReUploadCandidates();
|
||||
final sTime = DateTime.now().microsecondsSinceEpoch;
|
||||
// singleRunLimit indicates number of files to check during single
|
||||
// invocation of this method. The limit act as a crude way to limit the
|
||||
// resource consumed by the method
|
||||
const int singleRunLimit = 50;
|
||||
final localIDsToProcess =
|
||||
await _fileUpdationDB.getLocalIDsForPotentialReUpload(
|
||||
singleRunLimit,
|
||||
FileUpdationDB.livePhotoSize,
|
||||
);
|
||||
if (localIDsToProcess.isNotEmpty) {
|
||||
await _checkLivePhotoWithLowOrUnknownSize(
|
||||
localIDsToProcess,
|
||||
);
|
||||
final eTime = DateTime.now().microsecondsSinceEpoch;
|
||||
final d = Duration(microseconds: eTime - sTime);
|
||||
_logger.info(
|
||||
'Performed hashCheck for ${localIDsToProcess.length} livePhoto files '
|
||||
'completed in ${d.inSeconds.toString()} secs',
|
||||
);
|
||||
} else {
|
||||
_prefs.setBool(_iosLivePhotoSizeMigrationDone, true);
|
||||
}
|
||||
} catch (e, s) {
|
||||
_logger.severe('error while checking livePhotoSize check', e, s);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _checkLivePhotoWithLowOrUnknownSize(
|
||||
List<String> localIDsToProcess,
|
||||
) async {
|
||||
final int userID = Configuration.instance.getUserID()!;
|
||||
final List<EnteFile> result =
|
||||
await FilesDB.instance.getLocalFiles(localIDsToProcess);
|
||||
final List<EnteFile> localFilesForUser = [];
|
||||
final Set<String> localIDsWithFile = {};
|
||||
final Set<int> missingSizeIDs = {};
|
||||
for (EnteFile file in result) {
|
||||
if (file.ownerID == null || file.ownerID == userID) {
|
||||
localFilesForUser.add(file);
|
||||
localIDsWithFile.add(file.localID!);
|
||||
if (file.isUploaded && file.fileSize == null) {
|
||||
missingSizeIDs.add(file.uploadedFileID!);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (missingSizeIDs.isNotEmpty) {
|
||||
await FilesService.instance.backFillSizes(missingSizeIDs.toList());
|
||||
_logger.info('sizes back fill for ${missingSizeIDs.length} files');
|
||||
// return early, let the check run in the next batch
|
||||
return;
|
||||
}
|
||||
|
||||
final Set<String> processedIDs = {};
|
||||
// if a file for localID doesn't exist, then mark it as processed
|
||||
// otherwise the app will be stuck in retrying same set of ids
|
||||
|
||||
for (String localID in localIDsToProcess) {
|
||||
if (!localIDsWithFile.contains(localID)) {
|
||||
processedIDs.add(localID);
|
||||
}
|
||||
}
|
||||
_logger.info(" check ${localIDsToProcess.length} files for livePhotoSize, "
|
||||
"missing file cnt ${processedIDs.length}");
|
||||
|
||||
for (EnteFile file in localFilesForUser) {
|
||||
if (file.fileSize == null) {
|
||||
_logger.info('fileSize still null, skip this file');
|
||||
continue;
|
||||
} else if (file.fileType != FileType.livePhoto) {
|
||||
_logger.severe('fileType is not livePhoto, skip this file');
|
||||
continue;
|
||||
} else if (file.fileSize! != fourMBWithChunkSize) {
|
||||
// back-filled size is not of our interest
|
||||
processedIDs.add(file.localID!);
|
||||
continue;
|
||||
}
|
||||
if (processedIDs.contains(file.localID)) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
final MediaUploadData uploadData = await getUploadData(file);
|
||||
_logger.info(
|
||||
'Found livePhoto on local with hash ${uploadData.hashData?.fileHash ?? "null"} and existing hash ${file.hash ?? "null"}');
|
||||
await clearCache(file);
|
||||
await FilesDB.instance.markFilesForReUpload(
|
||||
userID,
|
||||
file.localID!,
|
||||
file.title,
|
||||
file.location,
|
||||
file.creationTime!,
|
||||
file.modificationTime!,
|
||||
file.fileType,
|
||||
);
|
||||
processedIDs.add(file.localID!);
|
||||
} on InvalidFileError catch (e) {
|
||||
if (e.reason == InvalidReason.livePhotoToImageTypeChanged ||
|
||||
e.reason == InvalidReason.imageToLivePhotoTypeChanged) {
|
||||
// let existing file update check handle this case
|
||||
_fileUpdationDB.insertMultiple(
|
||||
[file.localID!],
|
||||
FileUpdationDB.modificationTimeUpdated,
|
||||
).ignore();
|
||||
} else {
|
||||
_logger.severe("livePhoto check failed: invalid file ${file.tag}", e);
|
||||
}
|
||||
processedIDs.add(file.localID!);
|
||||
} catch (e) {
|
||||
_logger.severe("livePhoto check failed", e);
|
||||
} finally {}
|
||||
}
|
||||
await _fileUpdationDB.deleteByLocalIDs(
|
||||
processedIDs.toList(),
|
||||
FileUpdationDB.livePhotoSize,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _importLivePhotoReUploadCandidates() async {
|
||||
if (_prefs.containsKey(_doneLivePhotoImport)) {
|
||||
return;
|
||||
}
|
||||
_logger.info('_importLivePhotoReUploadCandidates');
|
||||
final EnteWatch watch = EnteWatch("_importLivePhotoReUploadCandidates");
|
||||
final int ownerID = Configuration.instance.getUserID()!;
|
||||
final List<String> localIDs = await FilesDB.instance
|
||||
.getLivePhotosWithBadSize(ownerID, fourMBWithChunkSize);
|
||||
await _fileUpdationDB.insertMultiple(
|
||||
localIDs,
|
||||
FileUpdationDB.livePhotoSize,
|
||||
);
|
||||
watch.log("imported ${localIDs.length} files");
|
||||
await _prefs.setBool(_doneLivePhotoImport, true);
|
||||
}
|
||||
|
||||
Future<MediaUploadData> getUploadData(EnteFile file) async {
|
||||
final mediaUploadData = await getUploadDataFromEnteFile(file);
|
||||
// delete the file from app's internal cache if it was copied to app
|
||||
|
|
|
@ -338,7 +338,7 @@ class UserService {
|
|||
Widget page;
|
||||
final String twoFASessionID = response.data["twoFactorSessionID"];
|
||||
if (twoFASessionID.isNotEmpty) {
|
||||
setTwoFactor(value: true);
|
||||
await setTwoFactor(value: true);
|
||||
page = TwoFactorAuthenticationPage(twoFASessionID);
|
||||
} else {
|
||||
await _saveConfiguration(response);
|
||||
|
@ -354,7 +354,7 @@ class UserService {
|
|||
);
|
||||
}
|
||||
}
|
||||
Navigator.of(context).pushAndRemoveUntil(
|
||||
await Navigator.of(context).pushAndRemoveUntil(
|
||||
MaterialPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
return page;
|
||||
|
@ -740,9 +740,10 @@ class UserService {
|
|||
);
|
||||
await dialog.hide();
|
||||
if (response.statusCode == 200) {
|
||||
showShortToast(context, S.of(context).authenticationSuccessful);
|
||||
showShortToast(context, S.of(context).authenticationSuccessful)
|
||||
.ignore();
|
||||
await _saveConfiguration(response);
|
||||
Navigator.of(context).pushAndRemoveUntil(
|
||||
await Navigator.of(context).pushAndRemoveUntil(
|
||||
MaterialPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
return const PasswordReentryPage();
|
||||
|
@ -755,8 +756,8 @@ class UserService {
|
|||
await dialog.hide();
|
||||
_logger.severe(e);
|
||||
if (e.response != null && e.response!.statusCode == 404) {
|
||||
showToast(context, "Session expired");
|
||||
Navigator.of(context).pushAndRemoveUntil(
|
||||
showToast(context, "Session expired").ignore();
|
||||
await Navigator.of(context).pushAndRemoveUntil(
|
||||
MaterialPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
return const LoginPage();
|
||||
|
@ -809,7 +810,7 @@ class UserService {
|
|||
} on DioError catch (e) {
|
||||
_logger.severe(e);
|
||||
if (e.response != null && e.response!.statusCode == 404) {
|
||||
showToast(context, S.of(context).sessionExpired);
|
||||
showToast(context, S.of(context).sessionExpired).ignore();
|
||||
Navigator.of(context).pushAndRemoveUntil(
|
||||
MaterialPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
|
@ -959,7 +960,7 @@ class UserService {
|
|||
try {
|
||||
recoveryKey = await getOrCreateRecoveryKey(context);
|
||||
} catch (e) {
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
return false;
|
||||
}
|
||||
final dialog = createProgressDialog(context, S.of(context).verifying);
|
||||
|
|
|
@ -289,7 +289,7 @@ class _DeleteAccountPageState extends State<DeleteAccountPage> {
|
|||
showShortToast(context, S.of(context).yourAccountHasBeenDeleted);
|
||||
} catch (e, s) {
|
||||
Logger("DeleteAccount").severe("failed to delete", e, s);
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -404,7 +404,7 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
|
|||
} catch (e, s) {
|
||||
_logger.severe(e, s);
|
||||
await dialog.hide();
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -456,7 +456,7 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
|
|||
} catch (e, s) {
|
||||
_logger.severe(e, s);
|
||||
await dialog.hide();
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -481,7 +481,7 @@ class _PasswordEntryPageState extends State<PasswordEntryPage> {
|
|||
S.of(context).sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease,
|
||||
);
|
||||
} else {
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,7 +109,7 @@ class _VerifyRecoveryPageState extends State<VerifyRecoveryPage> {
|
|||
),
|
||||
);
|
||||
} catch (e) {
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,7 +73,10 @@ extension CollectionFileActions on CollectionActions {
|
|||
);
|
||||
if (actionResult?.action != null &&
|
||||
actionResult!.action == ButtonAction.error) {
|
||||
showGenericErrorDialog(context: bContext, error: actionResult.exception);
|
||||
await showGenericErrorDialog(
|
||||
context: bContext,
|
||||
error: actionResult.exception,
|
||||
);
|
||||
} else {
|
||||
selectedFiles.clearAll();
|
||||
}
|
||||
|
@ -187,7 +190,7 @@ extension CollectionFileActions on CollectionActions {
|
|||
} catch (e, s) {
|
||||
logger.severe("Failed to add to album", e, s);
|
||||
await dialog?.hide();
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ class CollectionActions {
|
|||
_showUnSupportedAlert(context);
|
||||
} else {
|
||||
logger.severe("Failed to update shareUrl collection", e);
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -93,7 +93,10 @@ class CollectionActions {
|
|||
);
|
||||
if (actionResult?.action != null) {
|
||||
if (actionResult!.action == ButtonAction.error) {
|
||||
showGenericErrorDialog(context: context, error: actionResult.exception);
|
||||
await showGenericErrorDialog(
|
||||
context: context,
|
||||
error: actionResult.exception,
|
||||
);
|
||||
}
|
||||
return actionResult.action == ButtonAction.first;
|
||||
} else {
|
||||
|
@ -142,7 +145,7 @@ class CollectionActions {
|
|||
return collection;
|
||||
} catch (e, s) {
|
||||
dialog.hide();
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
logger.severe("Failing to create link for selected files", e, s);
|
||||
}
|
||||
return null;
|
||||
|
@ -183,7 +186,10 @@ class CollectionActions {
|
|||
);
|
||||
if (actionResult?.action != null) {
|
||||
if (actionResult!.action == ButtonAction.error) {
|
||||
showGenericErrorDialog(context: context, error: actionResult.exception);
|
||||
await showGenericErrorDialog(
|
||||
context: context,
|
||||
error: actionResult.exception,
|
||||
);
|
||||
}
|
||||
return actionResult.action == ButtonAction.first;
|
||||
}
|
||||
|
@ -230,7 +236,7 @@ class CollectionActions {
|
|||
} catch (e) {
|
||||
await dialog?.hide();
|
||||
logger.severe("Failed to get public key", e);
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
return false;
|
||||
}
|
||||
// getPublicKey can return null when no user is associated with given
|
||||
|
@ -272,7 +278,7 @@ class CollectionActions {
|
|||
_showUnSupportedAlert(context);
|
||||
} else {
|
||||
logger.severe("failed to share collection", e);
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -353,7 +359,10 @@ class CollectionActions {
|
|||
);
|
||||
if (actionResult?.action != null &&
|
||||
actionResult!.action == ButtonAction.error) {
|
||||
showGenericErrorDialog(context: bContext, error: actionResult.exception);
|
||||
await showGenericErrorDialog(
|
||||
context: bContext,
|
||||
error: actionResult.exception,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if ((actionResult?.action != null) &&
|
||||
|
|
|
@ -125,7 +125,10 @@ Future<void> showSingleFileDeleteSheet(
|
|||
);
|
||||
if (actionResult?.action != null &&
|
||||
actionResult!.action == ButtonAction.error) {
|
||||
showGenericErrorDialog(context: context, error: actionResult.exception);
|
||||
await showGenericErrorDialog(
|
||||
context: context,
|
||||
error: actionResult.exception,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -109,7 +109,7 @@ class AlbumVerticalListWidget extends StatelessWidget {
|
|||
textCapitalization: TextCapitalization.words,
|
||||
);
|
||||
if (result is Exception) {
|
||||
showGenericErrorDialog(
|
||||
await showGenericErrorDialog(
|
||||
context: context,
|
||||
error: result,
|
||||
);
|
||||
|
@ -311,7 +311,7 @@ class AlbumVerticalListWidget extends StatelessWidget {
|
|||
);
|
||||
return true;
|
||||
} catch (e) {
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -334,7 +334,7 @@ class AlbumVerticalListWidget extends StatelessWidget {
|
|||
),
|
||||
);
|
||||
} else {
|
||||
showGenericErrorDialog(context: context, error: result);
|
||||
await showGenericErrorDialog(context: context, error: result);
|
||||
_logger.severe("Cannot share collections owned by others");
|
||||
}
|
||||
}
|
||||
|
@ -356,7 +356,7 @@ class AlbumVerticalListWidget extends StatelessWidget {
|
|||
showGenericErrorDialog(
|
||||
context: context,
|
||||
error: Exception("Can not share collection owned by others"),
|
||||
);
|
||||
).ignore();
|
||||
_logger.severe("Cannot share collections owned by others");
|
||||
}
|
||||
return Future.value(true);
|
||||
|
@ -413,7 +413,7 @@ class AlbumVerticalListWidget extends StatelessWidget {
|
|||
} catch (e, s) {
|
||||
_logger.severe("Could not move to album", e, s);
|
||||
await dialog.hide();
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -442,7 +442,7 @@ class AlbumVerticalListWidget extends StatelessWidget {
|
|||
} catch (e, s) {
|
||||
_logger.severe("Could not move to album", e, s);
|
||||
await dialog.hide();
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ class NewAlbumIcon extends StatelessWidget {
|
|||
},
|
||||
);
|
||||
if (result is Exception) {
|
||||
showGenericErrorDialog(context: context, error: result);
|
||||
await showGenericErrorDialog(context: context, error: result);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
|
@ -49,13 +49,12 @@ class BottomActionBarWidget extends StatelessWidget {
|
|||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const SizedBox(height: 12),
|
||||
const SizedBox(height: 8),
|
||||
FileSelectionActionsWidget(
|
||||
galleryType,
|
||||
selectedFiles,
|
||||
collection: collection,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
const DividerWidget(dividerType: DividerType.bottomBar),
|
||||
ActionBarWidget(
|
||||
selectedFiles: selectedFiles,
|
||||
|
|
|
@ -498,7 +498,7 @@ class _ButtonChildWidgetState extends State<ButtonChildWidget> {
|
|||
} else if (exception != null) {
|
||||
//This is to show the execution was unsuccessful if the dialog is manually
|
||||
//closed before the execution completes.
|
||||
showGenericErrorDialog(context: context, error: exception);
|
||||
showGenericErrorDialog(context: context, error: exception).ignore();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -190,7 +190,7 @@ class _PaymentWebPageState extends State<PaymentWebPage> {
|
|||
} else {
|
||||
// should never reach here
|
||||
_logger.severe("unexpected status", uri.toString());
|
||||
showGenericErrorDialog(
|
||||
await showGenericErrorDialog(
|
||||
context: context,
|
||||
error: Exception("expected payment status $paymentStatus"),
|
||||
);
|
||||
|
|
|
@ -528,7 +528,7 @@ class _StoreSubscriptionPageState extends State<StoreSubscriptionPage> {
|
|||
response.notFoundIDs.toString();
|
||||
_logger.severe(errMsg);
|
||||
await _dialog.hide();
|
||||
showGenericErrorDialog(
|
||||
await showGenericErrorDialog(
|
||||
context: context,
|
||||
error: Exception(errMsg),
|
||||
);
|
||||
|
|
|
@ -303,20 +303,22 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
|
|||
await _launchStripePortal();
|
||||
break;
|
||||
case playStore:
|
||||
launchUrlString(
|
||||
"https://play.google.com/store/account/subscriptions?sku=" +
|
||||
_currentSubscription!.productID +
|
||||
"&package=io.ente.photos",
|
||||
unawaited(
|
||||
launchUrlString(
|
||||
"https://play.google.com/store/account/subscriptions?sku=" +
|
||||
_currentSubscription!.productID +
|
||||
"&package=io.ente.photos",
|
||||
),
|
||||
);
|
||||
break;
|
||||
case appStore:
|
||||
launchUrlString("https://apps.apple.com/account/billing");
|
||||
unawaited(launchUrlString("https://apps.apple.com/account/billing"));
|
||||
break;
|
||||
default:
|
||||
final String capitalizedWord = paymentProvider.isNotEmpty
|
||||
? '${paymentProvider[0].toUpperCase()}${paymentProvider.substring(1).toLowerCase()}'
|
||||
: '';
|
||||
showErrorDialog(
|
||||
await showErrorDialog(
|
||||
context,
|
||||
S.of(context).sorry,
|
||||
S.of(context).contactToManageSubscription(capitalizedWord),
|
||||
|
@ -328,7 +330,7 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
|
|||
await _dialog.show();
|
||||
try {
|
||||
final String url = await _billingService.getStripeCustomerPortalUrl();
|
||||
Navigator.of(context).push(
|
||||
await Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
return WebPage(S.of(context).paymentDetails, url);
|
||||
|
@ -337,7 +339,7 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
|
|||
).then((value) => onWebPaymentGoBack);
|
||||
} catch (e) {
|
||||
await _dialog.hide();
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
}
|
||||
await _dialog.hide();
|
||||
}
|
||||
|
@ -382,7 +384,7 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
|
|||
confirmAction = choice!.action == ButtonAction.first;
|
||||
}
|
||||
if (confirmAction) {
|
||||
toggleStripeSubscription(isRenewCancelled);
|
||||
await toggleStripeSubscription(isRenewCancelled);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
@ -398,11 +400,13 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
|
|||
: await _billingService.cancelStripeSubscription();
|
||||
await _fetchSub();
|
||||
} catch (e) {
|
||||
showShortToast(
|
||||
context,
|
||||
isAutoRenewDisabled
|
||||
? S.of(context).failedToRenew
|
||||
: S.of(context).failedToCancel,
|
||||
unawaited(
|
||||
showShortToast(
|
||||
context,
|
||||
isAutoRenewDisabled
|
||||
? S.of(context).failedToRenew
|
||||
: S.of(context).failedToCancel,
|
||||
),
|
||||
);
|
||||
}
|
||||
await _dialog.hide();
|
||||
|
@ -454,7 +458,7 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
|
|||
if (!_isStripeSubscriber &&
|
||||
_hasActiveSubscription &&
|
||||
_currentSubscription!.productID != freeProductID) {
|
||||
showErrorDialog(
|
||||
await showErrorDialog(
|
||||
context,
|
||||
S.of(context).sorry,
|
||||
S.of(context).cancelOtherSubscription(
|
||||
|
@ -473,7 +477,7 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
|
|||
"addOnBonus ${convertBytesToReadableFormat(addOnBonus)},"
|
||||
"overshooting by ${convertBytesToReadableFormat(_userDetails.getFamilyOrPersonalUsage() - (plan.storage + addOnBonus))}",
|
||||
);
|
||||
showErrorDialog(
|
||||
await showErrorDialog(
|
||||
context,
|
||||
S.of(context).sorry,
|
||||
S.of(context).youCannotDowngradeToThisPlan,
|
||||
|
@ -495,7 +499,7 @@ class _StripeSubscriptionPageState extends State<StripeSubscriptionPage> {
|
|||
return;
|
||||
}
|
||||
}
|
||||
Navigator.push(
|
||||
await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (BuildContext context) {
|
||||
|
|
|
@ -33,7 +33,7 @@ class ViewAddOnButton extends StatelessWidget {
|
|||
singleBorderRadius: 4,
|
||||
alignCaptionedTextToLeft: true,
|
||||
onTap: () async {
|
||||
routeToPage(context, AddOnPage(bonusData!));
|
||||
await routeToPage(context, AddOnPage(bonusData!));
|
||||
},
|
||||
),
|
||||
);
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import "dart:async";
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import "package:photos/core/error-reporting/super_logging.dart";
|
||||
import "package:photos/generated/l10n.dart";
|
||||
|
@ -106,8 +108,10 @@ class _AdvancedSettingsScreenState extends State<AdvancedSettingsScreen> {
|
|||
value: () =>
|
||||
MemoriesService.instance.showMemories,
|
||||
onChanged: () async {
|
||||
MemoriesService.instance.setShowMemories(
|
||||
!MemoriesService.instance.showMemories,
|
||||
unawaited(
|
||||
MemoriesService.instance.setShowMemories(
|
||||
!MemoriesService.instance.showMemories,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
|
|
@ -232,7 +232,7 @@ class _BackupFolderSelectionPageState extends State<BackupFolderSelectionPage> {
|
|||
} catch (e, s) {
|
||||
_logger.severe("Failed to updated backup folder", e, s);
|
||||
await dialog.hide();
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ class BackupSectionWidgetState extends State<BackupSectionWidget> {
|
|||
try {
|
||||
status = await SyncService.instance.getBackupStatus();
|
||||
} catch (e) {
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -128,7 +128,7 @@ class BackupSectionWidgetState extends State<BackupSectionWidget> {
|
|||
duplicates =
|
||||
await DeduplicationService.instance.getDuplicateFiles();
|
||||
} catch (e) {
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -217,7 +217,7 @@ class BackupSectionWidgetState extends State<BackupSectionWidget> {
|
|||
),
|
||||
firstButtonLabel: S.of(context).rateUs,
|
||||
firstButtonOnTap: () async {
|
||||
UpdateService.instance.launchReviewUrl();
|
||||
await UpdateService.instance.launchReviewUrl();
|
||||
},
|
||||
firstButtonType: ButtonType.primary,
|
||||
secondButtonLabel: S.of(context).ok,
|
||||
|
@ -225,7 +225,7 @@ class BackupSectionWidgetState extends State<BackupSectionWidget> {
|
|||
showShortToast(
|
||||
context,
|
||||
S.of(context).remindToEmptyEnteTrash,
|
||||
);
|
||||
).ignore();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ class DebugSectionWidget extends StatelessWidget {
|
|||
trailingIconIsMuted: true,
|
||||
onTap: () async {
|
||||
await LocalSyncService.instance.resetLocalSync();
|
||||
showShortToast(context, "Done");
|
||||
showShortToast(context, "Done").ignore();
|
||||
},
|
||||
),
|
||||
sectionOptionSpacing,
|
||||
|
@ -63,8 +63,8 @@ class DebugSectionWidget extends StatelessWidget {
|
|||
trailingIconIsMuted: true,
|
||||
onTap: () async {
|
||||
await IgnoredFilesService.instance.reset();
|
||||
SyncService.instance.sync();
|
||||
showShortToast(context, "Done");
|
||||
SyncService.instance.sync().ignore();
|
||||
showShortToast(context, "Done").ignore();
|
||||
},
|
||||
),
|
||||
sectionOptionSpacing,
|
||||
|
|
|
@ -68,7 +68,7 @@ class GeneralSectionWidget extends StatelessWidget {
|
|||
trailingIconIsMuted: true,
|
||||
onTap: () async {
|
||||
final locale = await getLocale();
|
||||
routeToPage(
|
||||
await routeToPage(
|
||||
context,
|
||||
LanguageSelectorPage(
|
||||
appSupportedLocales,
|
||||
|
|
|
@ -279,7 +279,7 @@ class _SecuritySectionWidgetState extends State<SecuritySectionWidget> {
|
|||
}
|
||||
await UserService.instance.updateEmailMFA(isEnabled);
|
||||
} catch (e) {
|
||||
showToast(context, S.of(context).somethingWentWrong);
|
||||
showToast(context, S.of(context).somethingWentWrong).ignore();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,7 +132,10 @@ class _ManageIndividualParticipantState
|
|||
CollectionParticipantRole.viewer,
|
||||
);
|
||||
} catch (e) {
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(
|
||||
context: context,
|
||||
error: e,
|
||||
);
|
||||
}
|
||||
if (isConvertToViewSuccess && mounted) {
|
||||
// reset value
|
||||
|
|
|
@ -137,7 +137,7 @@ class _ItemsWidgetState extends State<ItemsWidget> {
|
|||
try {
|
||||
await CollectionsService.instance.updateShareUrl(widget.collection, prop);
|
||||
} catch (e) {
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -180,7 +180,7 @@ class _ItemsWidgetState extends State<ItemsWidget> {
|
|||
try {
|
||||
await CollectionsService.instance.updateShareUrl(widget.collection, prop);
|
||||
} catch (e) {
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -319,21 +319,30 @@ class _FileSelectionActionsWidgetState
|
|||
);
|
||||
|
||||
if (items.isNotEmpty) {
|
||||
return SizedBox(
|
||||
width: double.infinity,
|
||||
child: Center(
|
||||
child: SingleChildScrollView(
|
||||
physics: const BouncingScrollPhysics(
|
||||
decelerationRate: ScrollDecelerationRate.fast,
|
||||
),
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(width: 4),
|
||||
...items,
|
||||
const SizedBox(width: 4),
|
||||
],
|
||||
final scrollController = ScrollController();
|
||||
// h4ck: https://github.com/flutter/flutter/issues/57920#issuecomment-893970066
|
||||
return MediaQuery(
|
||||
data: MediaQuery.of(context).removePadding(removeBottom: true),
|
||||
child: SafeArea(
|
||||
child: Scrollbar(
|
||||
controller: scrollController,
|
||||
thumbVisibility: true,
|
||||
child: SingleChildScrollView(
|
||||
physics: const BouncingScrollPhysics(
|
||||
decelerationRate: ScrollDecelerationRate.fast,
|
||||
),
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.only(bottom: 24),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(width: 4),
|
||||
...items,
|
||||
const SizedBox(width: 4),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -257,15 +257,15 @@ class FileAppBarState extends State<FileAppBar> {
|
|||
},
|
||||
onSelected: (dynamic value) async {
|
||||
if (value == 1) {
|
||||
_download(widget.file);
|
||||
await _download(widget.file);
|
||||
} else if (value == 2) {
|
||||
await _toggleFileArchiveStatus(widget.file);
|
||||
} else if (value == 3) {
|
||||
_setAs(widget.file);
|
||||
await _setAs(widget.file);
|
||||
} else if (value == 4) {
|
||||
_handleHideRequest(context);
|
||||
await _handleHideRequest(context);
|
||||
} else if (value == 5) {
|
||||
_handleUnHideRequest(context);
|
||||
await _handleUnHideRequest(context);
|
||||
}
|
||||
},
|
||||
),
|
||||
|
@ -371,7 +371,7 @@ class FileAppBarState extends State<FileAppBar> {
|
|||
} catch (e) {
|
||||
_logger.warning("Failed to save file", e);
|
||||
await dialog.hide();
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
} finally {
|
||||
PhotoManager.startChangeNotify();
|
||||
LocalSyncService.instance.checkAndSync().ignore();
|
||||
|
@ -432,7 +432,7 @@ class FileAppBarState extends State<FileAppBar> {
|
|||
} catch (e) {
|
||||
dialog.hide();
|
||||
_logger.severe("Failed to use as", e);
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import "dart:async";
|
||||
|
||||
import "package:flutter/material.dart";
|
||||
import "package:like_button/like_button.dart";
|
||||
import "package:logging/logging.dart";
|
||||
|
@ -77,9 +79,11 @@ class _FavoriteWidgetState extends State<FavoriteWidget> {
|
|||
} catch (e, s) {
|
||||
_logger.severe(e, s);
|
||||
hasError = true;
|
||||
showToast(
|
||||
context,
|
||||
S.of(context).sorryCouldNotRemoveFromFavorites,
|
||||
unawaited(
|
||||
showToast(
|
||||
context,
|
||||
S.of(context).sorryCouldNotRemoveFromFavorites,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ class EmptyAlbumState extends StatelessWidget {
|
|||
try {
|
||||
await showAddPhotosSheet(context, c);
|
||||
} catch (e) {
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
}
|
||||
},
|
||||
),
|
||||
|
|
|
@ -131,6 +131,11 @@ class GalleryState extends State<Gallery> {
|
|||
"Reloaded gallery on soft refresh all files on ${event.reason}",
|
||||
);
|
||||
}
|
||||
if (event.type == EventType.deletedFromDevice ||
|
||||
event.type == EventType.deletedFromEverywhere ||
|
||||
event.type == EventType.deletedFromRemote) {
|
||||
setState(() {});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -172,7 +172,7 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
|
|||
},
|
||||
);
|
||||
if (result is Exception) {
|
||||
showGenericErrorDialog(context: context, error: result);
|
||||
await showGenericErrorDialog(context: context, error: result);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,7 +204,10 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
|
|||
);
|
||||
if (actionResult?.action != null && mounted) {
|
||||
if (actionResult!.action == ButtonAction.error) {
|
||||
showGenericErrorDialog(context: context, error: actionResult.exception);
|
||||
await showGenericErrorDialog(
|
||||
context: context,
|
||||
error: actionResult.exception,
|
||||
);
|
||||
} else if (actionResult.action == ButtonAction.first) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
|
@ -224,7 +227,7 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
|
|||
.getBackupStatus(pathID: widget.deviceCollection!.id);
|
||||
} catch (e) {
|
||||
await dialog.hide();
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
unawaited(showGenericErrorDialog(context: context, error: e));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -664,7 +667,7 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
|
|||
} catch (e, s) {
|
||||
_logger.severe("failed to trash collection", e, s);
|
||||
await dialog.hide();
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
}
|
||||
} else {
|
||||
final bool result = await collectionActions.deleteCollectionSheet(
|
||||
|
@ -691,7 +694,7 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
|
|||
}
|
||||
} catch (e, s) {
|
||||
_logger.severe("failed to trash collection", e, s);
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -726,7 +729,7 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
|
|||
}
|
||||
} catch (e, s) {
|
||||
_logger.severe(e, s);
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -736,7 +739,7 @@ class _GalleryAppBarWidgetState extends State<GalleryAppBarWidget> {
|
|||
await showAddPhotosSheet(bContext, collection!);
|
||||
} catch (e, s) {
|
||||
_logger.severe(e, s);
|
||||
showGenericErrorDialog(context: bContext, error: e);
|
||||
await showGenericErrorDialog(context: bContext, error: e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -205,7 +205,7 @@ class AddPhotosPhotoWidget extends StatelessWidget {
|
|||
if (e is StateError) {
|
||||
final PermissionState ps = await PhotoManager.requestPermissionExtend();
|
||||
if (ps != PermissionState.authorized && ps != PermissionState.limited) {
|
||||
showChoiceDialog(
|
||||
await showChoiceDialog(
|
||||
context,
|
||||
title: context.l10n.grantPermission,
|
||||
body: context.l10n.pleaseGrantPermissions,
|
||||
|
|
|
@ -118,7 +118,7 @@ class LocationScreenPopUpMenu extends StatelessWidget {
|
|||
);
|
||||
Navigator.of(context).pop();
|
||||
} catch (e) {
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -102,7 +102,7 @@ Future<void> deleteFilesFromEverywhere(
|
|||
await FilesDB.instance.deleteMultipleUploadedFiles(fileIDs);
|
||||
} catch (e) {
|
||||
_logger.severe(e);
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
rethrow;
|
||||
}
|
||||
for (final collectionID in updatedCollectionIDs) {
|
||||
|
@ -127,9 +127,9 @@ Future<void> deleteFilesFromEverywhere(
|
|||
),
|
||||
);
|
||||
if (hasLocalOnlyFiles && Platform.isAndroid) {
|
||||
showShortToast(context, S.of(context).filesDeleted);
|
||||
await showShortToast(context, S.of(context).filesDeleted);
|
||||
} else {
|
||||
showShortToast(context, S.of(context).movedToTrash);
|
||||
await showShortToast(context, S.of(context).movedToTrash);
|
||||
}
|
||||
}
|
||||
if (uploadedFilesToBeTrashed.isNotEmpty) {
|
||||
|
@ -163,7 +163,7 @@ Future<void> deleteFilesFromRemoteOnly(
|
|||
await FilesDB.instance.deleteMultipleUploadedFiles(uploadedFileIDs);
|
||||
} catch (e, s) {
|
||||
_logger.severe("Failed to delete files from remote", e, s);
|
||||
showGenericErrorDialog(context: context, error: e);
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
rethrow;
|
||||
}
|
||||
for (final collectionID in updatedCollectionIDs) {
|
||||
|
@ -626,7 +626,10 @@ Future<void> showDeleteSheet(
|
|||
);
|
||||
if (actionResult?.action != null &&
|
||||
actionResult!.action == ButtonAction.error) {
|
||||
showGenericErrorDialog(context: context, error: actionResult.exception);
|
||||
await showGenericErrorDialog(
|
||||
context: context,
|
||||
error: actionResult.exception,
|
||||
);
|
||||
} else {
|
||||
selectedFiles.clearAll();
|
||||
}
|
||||
|
|
|
@ -204,7 +204,7 @@ Future<File?> _getLivePhotoFromServer(
|
|||
return needLiveVideo ? livePhoto.video : livePhoto.image;
|
||||
} catch (e, s) {
|
||||
_logger.warning("live photo get failed", e, s);
|
||||
_livePhotoDownloadsTracker.remove(downloadID);
|
||||
await _livePhotoDownloadsTracker.remove(downloadID);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -348,9 +348,9 @@ Future<Uint8List> compressThumbnail(Uint8List thumbnail) {
|
|||
|
||||
Future<void> clearCache(EnteFile file) async {
|
||||
if (file.fileType == FileType.video) {
|
||||
VideoCacheManager.instance.removeFile(file.downloadUrl);
|
||||
await VideoCacheManager.instance.removeFile(file.downloadUrl);
|
||||
} else {
|
||||
DefaultCacheManager().removeFile(file.downloadUrl);
|
||||
await DefaultCacheManager().removeFile(file.downloadUrl);
|
||||
}
|
||||
final cachedThumbnail = File(
|
||||
Configuration.instance.getThumbnailCacheDirectory() +
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import "dart:async";
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:path/path.dart';
|
||||
|
@ -134,7 +136,7 @@ Future<void> updateOrder(
|
|||
);
|
||||
} catch (e, s) {
|
||||
_logger.severe("failed to update order", e, s);
|
||||
showShortToast(context, S.of(context).somethingWentWrong);
|
||||
unawaited(showShortToast(context, S.of(context).somethingWentWrong));
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
@ -160,7 +162,7 @@ Future<void> changeCoverPhoto(
|
|||
);
|
||||
} catch (e, s) {
|
||||
_logger.severe("failed to update cover", e, s);
|
||||
showShortToast(context, S.of(context).somethingWentWrong);
|
||||
unawaited(showShortToast(context, S.of(context).somethingWentWrong));
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
@ -179,7 +181,7 @@ Future<bool> editTime(
|
|||
);
|
||||
return true;
|
||||
} catch (e) {
|
||||
showShortToast(context, S.of(context).somethingWentWrong);
|
||||
showShortToast(context, S.of(context).somethingWentWrong).ignore();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -218,7 +220,7 @@ Future<void> editFilename(
|
|||
);
|
||||
if (result is Exception) {
|
||||
_logger.severe("Failed to rename file");
|
||||
showGenericErrorDialog(context: context, error: result);
|
||||
await showGenericErrorDialog(context: context, error: result);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -238,7 +240,7 @@ Future<bool> editFileCaption(
|
|||
return true;
|
||||
} catch (e) {
|
||||
if (context != null) {
|
||||
showShortToast(context, S.of(context).somethingWentWrong);
|
||||
unawaited(showShortToast(context, S.of(context).somethingWentWrong));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -265,7 +267,7 @@ Future<void> _updatePublicMetadata(
|
|||
await FileMagicService.instance.updatePublicMagicMetadata(files, update);
|
||||
if (context != null) {
|
||||
if (showDoneToast) {
|
||||
showShortToast(context, S.of(context).done);
|
||||
await showShortToast(context, S.of(context).done);
|
||||
}
|
||||
await dialog?.hide();
|
||||
}
|
||||
|
|
11
pubspec.lock
11
pubspec.lock
|
@ -503,11 +503,12 @@ packages:
|
|||
file_saver:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: file_saver
|
||||
sha256: "591d25e750e3a4b654f7b0293abc2ed857242f82ca7334051b2a8ceeb369dac8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.8"
|
||||
path: "."
|
||||
ref: HEAD
|
||||
resolved-ref: "01b2e6b6fe520cfa5d2d91342ccbfbaefa8f6482"
|
||||
url: "https://github.com/jesims/file_saver.git"
|
||||
source: git
|
||||
version: "0.2.9"
|
||||
firebase_core:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
@ -55,8 +55,10 @@ dependencies:
|
|||
extended_image: ^8.1.1
|
||||
fade_indexed_stack: ^0.2.2
|
||||
fast_base58: ^0.2.1
|
||||
# https://github.com/incrediblezayed/file_saver/issues/86
|
||||
file_saver: 0.2.8
|
||||
|
||||
file_saver:
|
||||
# Use forked version till this PR is merged: https://github.com/incrediblezayed/file_saver/pull/87
|
||||
git: https://github.com/jesims/file_saver.git
|
||||
firebase_core: ^2.13.1
|
||||
firebase_messaging: ^14.6.2
|
||||
fk_user_agent: ^2.0.1
|
||||
|
|
Loading…
Add table
Reference in a new issue