diff --git a/lib/controls/search_result_status_control.dart b/lib/controls/search_result_status_control.dart index 6540f86..5ec6e36 100644 --- a/lib/controls/search_result_status_control.dart +++ b/lib/controls/search_result_status_control.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; import 'package:logging/logging.dart'; +import 'package:provider/provider.dart'; import '../models/timeline_entry.dart'; +import '../services/auth_service.dart'; import '../utils/clipboard_utils.dart'; import '../utils/url_opening_utils.dart'; import 'html_text_viewer_control.dart'; @@ -127,6 +129,25 @@ class _SearchResultStatusControlState extends State { if (items.isEmpty) { return const SizedBox(); } + + // A Link Preview with only one media attachment will have a duplicate image + // even though it points to different resources server side. So we don't + // want to render it twice. + if (widget.status.linkPreviewData != null && items.length == 1) { + return const SizedBox(); + } + + // A Diaspora reshare will have an HTML-built card with a link preview image + // to the same image as what would be in the single attachment but at a + // different link. So we don't want it to render twice. + final linkPhotoBaseUrl = Uri.https( + context.read().currentProfile.serverName, + 'photo/link', + ).toString(); + if (widget.status.body.contains(linkPhotoBaseUrl) && items.length == 1) { + return const SizedBox(); + } + return SizedBox( height: 250.0, child: ListView.separated( diff --git a/lib/controls/timeline/flattened_tree_entry_control.dart b/lib/controls/timeline/flattened_tree_entry_control.dart index 19c9e5f..e52939f 100644 --- a/lib/controls/timeline/flattened_tree_entry_control.dart +++ b/lib/controls/timeline/flattened_tree_entry_control.dart @@ -10,6 +10,7 @@ import '../../globals.dart'; import '../../models/filters/timeline_entry_filter.dart'; import '../../models/flattened_tree_item.dart'; import '../../models/timeline_entry.dart'; +import '../../services/auth_service.dart'; import '../../services/timeline_entry_filter_service.dart'; import '../../services/timeline_manager.dart'; import '../../utils/active_profile_selector.dart'; @@ -228,6 +229,25 @@ class _StatusControlState extends State { if (items.isEmpty) { return const SizedBox(); } + + // A Link Preview with only one media attachment will have a duplicate image + // even though it points to different resources server side. So we don't + // want to render it twice. + if (entry.linkPreviewData != null && items.length == 1) { + return const SizedBox(); + } + + // A Diaspora reshare will have an HTML-built card with a link preview image + // to the same image as what would be in the single attachment but at a + // different link. So we don't want it to render twice. + final linkPhotoBaseUrl = Uri.https( + context.read().currentProfile.serverName, + 'photo/link', + ).toString(); + if (entry.body.contains(linkPhotoBaseUrl) && items.length == 1) { + return const SizedBox(); + } + return SizedBox( height: ResponsiveSizesCalculator(context).maxThumbnailHeight, child: ListView.separated(