Add Diaspora post photo w/local caching (if downloaded)

This commit is contained in:
Hank Grabowski 2022-03-09 17:08:22 -05:00
parent 096c4ce3db
commit 0f59ec3afb
3 changed files with 62 additions and 12 deletions

View file

@ -0,0 +1,27 @@
import '../../models/media_attachment.dart';
import '../../utils/offsetdatetime_utils.dart';
MediaAttachment mediaAttachmentfromDiasporaJson(Map<String, dynamic> 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);
}

View file

@ -7,6 +7,7 @@ import 'package:markdown/markdown.dart';
import 'package:result_monad/result_monad.dart'; import 'package:result_monad/result_monad.dart';
import '../../services/connections_manager.dart'; import '../../services/connections_manager.dart';
import 'diaspora_media_attachment_serializer.dart';
final _logger = Logger('DiasporaPostsSerializer'); final _logger = Logger('DiasporaPostsSerializer');
const _statusMessageType = 'status_message'; const _statusMessageType = 'status_message';
@ -75,11 +76,15 @@ Result<TimelineEntry, ExecError> _buildStatusMessageType(
final authorName = entityData['author'] ?? ''; final authorName = entityData['author'] ?? '';
final author = final author =
connections.getByName(authorName).getValueOrElse(() => Connection()); connections.getByName(authorName).getValueOrElse(() => Connection());
final photos = (entityData['photos'] as List<dynamic>? ?? [])
.map((e) => mediaAttachmentfromDiasporaJson(e));
final timelineEntry = TimelineEntry( final timelineEntry = TimelineEntry(
id: postId, id: postId,
creationTimestamp: epochTime, creationTimestamp: epochTime,
body: postHtml, body: postHtml,
author: author.name, author: author.name,
mediaAttachments: photos.toList(),
authorId: author.id); authorId: author.id);
return Result.ok(timelineEntry); return Result.ok(timelineEntry);
} }

View file

@ -1,4 +1,3 @@
import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:friendica_archive_browser/src/diaspora/services/diaspora_path_mapping_service.dart'; 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 DiasporaPathMappingService pathMappingService;
final Map<String, ImageEntry> _imagesByRequestUrl = {}; final Map<String, ImageEntry> _imagesByRequestUrl = {};
final List<FileSystemEntity> _topLevelDirectories = [];
final List<EntryTreeItem> _postEntries = []; final List<EntryTreeItem> _postEntries = [];
final List<EntryTreeItem> _orphanedCommentEntries = []; final List<EntryTreeItem> _orphanedCommentEntries = [];
final List<EntryTreeItem> _allComments = []; final List<EntryTreeItem> _allComments = [];
@ -35,6 +35,7 @@ class DiasporaArchiveService implements ArchiveService {
_orphanedCommentEntries.clear(); _orphanedCommentEntries.clear();
_allComments.clear(); _allComments.clear();
_postEntries.clear(); _postEntries.clear();
_topLevelDirectories.clear();
} }
FutureResult<List<EntryTreeItem>, ExecError> getPosts() async { FutureResult<List<EntryTreeItem>, ExecError> getPosts() async {
@ -63,10 +64,17 @@ class DiasporaArchiveService implements ArchiveService {
Result<ImageEntry, ExecError> getImageByUrl(String url) { Result<ImageEntry, ExecError> getImageByUrl(String url) {
if (_imagesByRequestUrl.isEmpty) { 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 return result == null
? Result.error(ExecError(errorMessage: '$url not found')) ? Result.error(ExecError(errorMessage: '$url not found'))
: Result.ok(result); : 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() { void _populateTopLevelSubDirectory() {
final imageJsonPath = p.join(_baseArchiveFolder, 'images.json'); final topLevelDirectories = Directory(_baseArchiveFolder)
final jsonFile = File(imageJsonPath); .listSync(recursive: false)
if (jsonFile.existsSync()) { .where((e) => e.statSync().type == FileSystemEntityType.directory);
final json = jsonDecode(jsonFile.readAsStringSync()) as List<dynamic>; _topLevelDirectories.addAll(topLevelDirectories);
final imageEntries = json.map((j) => ImageEntry.fromJson(j)); }
for (final entry in imageEntries) {
_imagesByRequestUrl[entry.url] = entry; Result<ImageEntry, ExecError> _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'));
} }
} }