upload non finished uploads after restart

This commit is contained in:
otsmr 2025-10-29 10:14:25 +01:00
parent cb1ad9bdc7
commit 404aee1e18
6 changed files with 54 additions and 5 deletions

View file

@ -17,6 +17,7 @@ import 'package:twonly/src/providers/image_editor.provider.dart';
import 'package:twonly/src/providers/settings.provider.dart';
import 'package:twonly/src/services/api.service.dart';
import 'package:twonly/src/services/api/mediafiles/media_background.service.dart';
import 'package:twonly/src/services/api/mediafiles/upload.service.dart';
import 'package:twonly/src/services/fcm.service.dart';
import 'package:twonly/src/services/mediafiles/mediafile.service.dart';
import 'package:twonly/src/utils/log.dart';
@ -55,6 +56,7 @@ void main() async {
twonlyDB = TwonlyDB();
await initFileDownloader();
unawaited(finishStartedPreprocessing());
unawaited(MediaFileService.purgeTempFolder());
await twonlyDB.messagesDao.purgeMessageTable();

View file

@ -84,6 +84,16 @@ class MediaFilesDao extends DatabaseAccessor<TwonlyDB>
.get();
}
Future<List<MediaFile>> getAllMediaFilesPendingUpload() async {
return (select(mediaFiles)
..where(
(t) =>
t.uploadState.equals(UploadState.initialized.name) |
t.uploadState.equals(UploadState.preprocessing.name),
))
.get();
}
Stream<List<MediaFile>> watchAllStoredMediaFiles() {
return (select(mediaFiles)..where((t) => t.stored.equals(true))).watch();
}

View file

@ -19,6 +19,20 @@ import 'package:twonly/src/services/mediafiles/mediafile.service.dart';
import 'package:twonly/src/utils/log.dart';
import 'package:twonly/src/utils/misc.dart';
Future<void> finishStartedPreprocessing() async {
final mediaFiles =
await twonlyDB.mediaFilesDao.getAllMediaFilesPendingUpload();
for (final mediaFile in mediaFiles) {
try {
final service = await MediaFileService.fromMedia(mediaFile);
await startBackgroundMediaUpload(service);
} catch (e) {
Log.error(e);
}
}
}
Future<MediaFileService?> initializeMediaUpload(
MediaType type,
int? displayLimitInMilliseconds,
@ -77,15 +91,22 @@ Future<void> startBackgroundMediaUpload(MediaFileService mediaService) async {
if (!mediaService.tempPath.existsSync()) {
await mediaService.compressMedia();
if (!mediaService.tempPath.existsSync()) {
return;
}
}
if (!mediaService.encryptedPath.existsSync()) {
await _encryptMediaFiles(mediaService);
if (!mediaService.encryptedPath.existsSync()) {
return;
}
}
if (!mediaService.uploadRequestPath.existsSync()) {
await _createUploadRequest(mediaService);
}
if (mediaService.uploadRequestPath.existsSync()) {
await mediaService.setUploadState(UploadState.uploading);
// at this point the original file is not used any more, so it can be deleted
@ -101,6 +122,11 @@ Future<void> startBackgroundMediaUpload(MediaFileService mediaService) async {
Future<void> _encryptMediaFiles(MediaFileService mediaService) async {
/// if there is a video wait until it is finished with compression
if (!mediaService.tempPath.existsSync()) {
Log.error('Could not encrypted image as it does not exists');
return;
}
final dataToEncrypt = await mediaService.tempPath.readAsBytes();
final chacha20 = FlutterChacha20.poly1305Aead();

View file

@ -10,7 +10,7 @@ Future<void> createThumbnailsForVideo(
final stopwatch = Stopwatch()..start();
final command =
'-i ${sourceFile.path} -ss 00:00:00 -vframes 1 -vf "scale=iw:ih:flags=lanczos" -c:v libwebp -q:v 100 -compression_level 6 ${destinationFile.path}';
'-i "${sourceFile.path}" -ss 00:00:00 -vframes 1 -vf "scale=iw:ih:flags=lanczos" -c:v libwebp -q:v 100 -compression_level 6 "${destinationFile.path}"';
final session = await FFmpegKit.execute(command);
final returnCode = await session.getReturnCode();
@ -22,8 +22,9 @@ Future<void> createThumbnailsForVideo(
);
} else {
Log.info(command);
Log.error('Compression failed for the video with exit code $returnCode.');
Log.error(
'Thumbnail creation failed for the video with exit code $returnCode.',
);
Log.error(await session.getAllLogsAsString());
// Report this error to the user?
}
}

View file

@ -108,7 +108,6 @@ class ChatTextEntry extends StatelessWidget {
),
),
),
// if (displayTime)
Text(
friendlyTime(
context,

View file

@ -20,9 +20,19 @@ class MemoriesItemThumbnail extends StatefulWidget {
class _MemoriesItemThumbnailState extends State<MemoriesItemThumbnail> {
@override
void initState() {
initAsync();
super.initState();
}
Future<void> initAsync() async {
if (!widget.galleryItem.mediaService.thumbnailPath.existsSync()) {
if (widget.galleryItem.mediaService.storedPath.existsSync()) {
await widget.galleryItem.mediaService.createThumbnail();
if (mounted) setState(() {});
}
}
}
@override
void dispose() {
super.dispose();
@ -46,7 +56,8 @@ class _MemoriesItemThumbnailState extends State<MemoriesItemThumbnail> {
children: [
if (media.thumbnailPath.existsSync())
Image.file(media.thumbnailPath)
else if (media.storedPath.existsSync())
else if (media.storedPath.existsSync() &&
media.mediaFile.type == MediaType.image)
Image.file(media.storedPath)
else
const Text('Media file removed.'),