diff --git a/friendica_archive_browser/lib/src/diaspora/serializers/diaspora_media_attachment_serializer.dart b/friendica_archive_browser/lib/src/diaspora/serializers/diaspora_media_attachment_serializer.dart new file mode 100644 index 0000000..5c9ca08 --- /dev/null +++ b/friendica_archive_browser/lib/src/diaspora/serializers/diaspora_media_attachment_serializer.dart @@ -0,0 +1,27 @@ +import '../../models/media_attachment.dart'; +import '../../utils/offsetdatetime_utils.dart'; + +MediaAttachment mediaAttachmentfromDiasporaJson(Map json) { + final entityData = json['entity_data'] ?? {}; + final createdAtString = entityData['created_at'] ?? ''; + final creationTimestamp = + OffsetDateTimeUtils.epochSecTimeFromTimeZoneString(createdAtString) + .getValueOrElse(() => -1); + String uriBase = entityData['remote_photo_path'] ?? ''; + final photoName = entityData['remote_photo_name'] ?? ''; + final separator = uriBase.endsWith('/') ? '' : '/'; + final uri = Uri.parse('$uriBase$separator$photoName'); + const explicitType = AttachmentMediaType.image; + final thumbnailUri = Uri(); + const title = ''; + const description = ''; + + return MediaAttachment( + uri: uri, + creationTimestamp: creationTimestamp, + thumbnailUri: thumbnailUri, + metadata: {}, + title: title, + explicitType: explicitType, + description: description); +} diff --git a/friendica_archive_browser/lib/src/diaspora/serializers/diaspora_posts_serializer.dart b/friendica_archive_browser/lib/src/diaspora/serializers/diaspora_posts_serializer.dart index c398397..e2d1087 100644 --- a/friendica_archive_browser/lib/src/diaspora/serializers/diaspora_posts_serializer.dart +++ b/friendica_archive_browser/lib/src/diaspora/serializers/diaspora_posts_serializer.dart @@ -7,6 +7,7 @@ import 'package:markdown/markdown.dart'; import 'package:result_monad/result_monad.dart'; import '../../services/connections_manager.dart'; +import 'diaspora_media_attachment_serializer.dart'; final _logger = Logger('DiasporaPostsSerializer'); const _statusMessageType = 'status_message'; @@ -75,11 +76,15 @@ Result _buildStatusMessageType( final authorName = entityData['author'] ?? ''; final author = connections.getByName(authorName).getValueOrElse(() => Connection()); + final photos = (entityData['photos'] as List? ?? []) + .map((e) => mediaAttachmentfromDiasporaJson(e)); + final timelineEntry = TimelineEntry( id: postId, creationTimestamp: epochTime, body: postHtml, author: author.name, + mediaAttachments: photos.toList(), authorId: author.id); return Result.ok(timelineEntry); } diff --git a/friendica_archive_browser/lib/src/diaspora/services/diaspora_archive_service.dart b/friendica_archive_browser/lib/src/diaspora/services/diaspora_archive_service.dart index 980142a..6dccaa9 100644 --- a/friendica_archive_browser/lib/src/diaspora/services/diaspora_archive_service.dart +++ b/friendica_archive_browser/lib/src/diaspora/services/diaspora_archive_service.dart @@ -1,4 +1,3 @@ -import 'dart:convert'; import 'dart:io'; import 'package:friendica_archive_browser/src/diaspora/services/diaspora_path_mapping_service.dart'; @@ -17,6 +16,7 @@ class DiasporaArchiveService implements ArchiveService { final DiasporaPathMappingService pathMappingService; final Map _imagesByRequestUrl = {}; + final List _topLevelDirectories = []; final List _postEntries = []; final List _orphanedCommentEntries = []; final List _allComments = []; @@ -35,6 +35,7 @@ class DiasporaArchiveService implements ArchiveService { _orphanedCommentEntries.clear(); _allComments.clear(); _postEntries.clear(); + _topLevelDirectories.clear(); } FutureResult, ExecError> getPosts() async { @@ -63,10 +64,17 @@ class DiasporaArchiveService implements ArchiveService { Result getImageByUrl(String url) { if (_imagesByRequestUrl.isEmpty) { - _loadImages(); + _populateTopLevelSubDirectory(); } - final result = _imagesByRequestUrl[url]; + var result = _imagesByRequestUrl[url]; + if (result == null) { + final localFile = _getLocalVersion(url); + if (localFile.isSuccess) { + _imagesByRequestUrl[url] = localFile.value; + result = localFile.value; + } + } return result == null ? Result.error(ExecError(errorMessage: '$url not found')) : Result.ok(result); @@ -91,18 +99,28 @@ class DiasporaArchiveService implements ArchiveService { } } - _postEntries.sort((p1,p2)=>p2.entry.creationTimestamp.compareTo(p1.entry.creationTimestamp)); + _postEntries.sort((p1, p2) => + p2.entry.creationTimestamp.compareTo(p1.entry.creationTimestamp)); } - void _loadImages() { - final imageJsonPath = p.join(_baseArchiveFolder, 'images.json'); - final jsonFile = File(imageJsonPath); - if (jsonFile.existsSync()) { - final json = jsonDecode(jsonFile.readAsStringSync()) as List; - final imageEntries = json.map((j) => ImageEntry.fromJson(j)); - for (final entry in imageEntries) { - _imagesByRequestUrl[entry.url] = entry; + void _populateTopLevelSubDirectory() { + final topLevelDirectories = Directory(_baseArchiveFolder) + .listSync(recursive: false) + .where((e) => e.statSync().type == FileSystemEntityType.directory); + _topLevelDirectories.addAll(topLevelDirectories); + } + + Result _getLocalVersion(String url) { + final filename = Uri.parse(url).pathSegments.last; + for (final dir in _topLevelDirectories) { + final newPath = p.join(dir.path, filename); + if (File(newPath).existsSync()) { + final imageEntry = + ImageEntry(postId: '', localFilename: newPath, url: url); + return Result.ok(imageEntry); } } + + return Result.error(ExecError.message('Local file not found')); } }