mirror of
https://gitlab.com/mysocialportal/fediverse-archiving-tools.git
synced 2024-10-18 08:53:31 +00:00
Refactoring naming to be less Facebook centric (not totally excised)
This commit is contained in:
parent
5fbd79e20e
commit
0c47ad1432
34 changed files with 314 additions and 777 deletions
|
@ -52,7 +52,7 @@ class FriendicaArchiveBrowser extends StatelessWidget {
|
|||
theme: FriendicaArchiveBrowserTheme.light,
|
||||
darkTheme: FriendicaArchiveBrowserTheme.dark,
|
||||
themeMode: settingsController.themeMode,
|
||||
scrollBehavior: FacebookAppScrollingBehavior(),
|
||||
scrollBehavior: AppScrollingBehavior(),
|
||||
home: MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider(create: (context) => settingsController),
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_comment.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/friendica_comment.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/services/path_mapping_service.dart';
|
||||
import 'package:friendica_archive_browser/src/settings/settings_controller.dart';
|
||||
import 'package:friendica_archive_browser/src/utils/clipboard_helper.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'facebook_link_elements_component.dart';
|
||||
import 'facebook_media_timeline_component.dart';
|
||||
import 'link_elements_component.dart';
|
||||
import 'media_timeline_component.dart';
|
||||
|
||||
class CommentCard extends StatelessWidget {
|
||||
final FacebookComment comment;
|
||||
final FriendicaComment comment;
|
||||
|
||||
const CommentCard({Key? key, required this.comment}) : super(key: key);
|
||||
|
||||
|
@ -64,12 +64,11 @@ class CommentCard extends StatelessWidget {
|
|||
],
|
||||
if (comment.links.isNotEmpty) ...[
|
||||
const SizedBox(height: spacingHeight),
|
||||
FacebookLinkElementsComponent(links: comment.links)
|
||||
LinkElementsComponent(links: comment.links)
|
||||
],
|
||||
if (comment.mediaAttachments.isNotEmpty) ...[
|
||||
const SizedBox(height: spacingHeight),
|
||||
FacebookMediaTimelineComponent(
|
||||
mediaAttachments: comment.mediaAttachments)
|
||||
MediaTimelineComponent(mediaAttachments: comment.mediaAttachments)
|
||||
],
|
||||
],
|
||||
),
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import 'dart:ui';
|
||||
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_post.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/friendica_post.dart';
|
||||
import 'package:latlng/latlng.dart';
|
||||
import 'package:map/map.dart';
|
||||
|
||||
import 'marker_data.dart';
|
||||
|
||||
extension GeoSpatialPostExtensions on FacebookPost {
|
||||
extension GeoSpatialPostExtensions on FriendicaPost {
|
||||
MarkerData toMarkerData(MapTransformer transformer, Color color) {
|
||||
final latLon = LatLng(locationData.latitude, locationData.longitude);
|
||||
final offset = transformer.fromLatLngToXYCoords(latLon);
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import 'dart:ui';
|
||||
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_post.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/friendica_post.dart';
|
||||
|
||||
class MarkerData {
|
||||
final List<FacebookPost> posts;
|
||||
final List<FriendicaPost> posts;
|
||||
final Offset pos;
|
||||
final Color color;
|
||||
|
||||
|
|
|
@ -4,23 +4,21 @@ import 'package:logging/logging.dart';
|
|||
import 'package:metadata_fetch/metadata_fetch.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class FacebookLinkElementsComponent extends StatefulWidget {
|
||||
static final _logger = Logger('$FacebookLinkElementsComponent');
|
||||
class LinkElementsComponent extends StatefulWidget {
|
||||
static final _logger = Logger('$LinkElementsComponent');
|
||||
final List<Uri> links;
|
||||
|
||||
const FacebookLinkElementsComponent({Key? key, required this.links})
|
||||
const LinkElementsComponent({Key? key, required this.links})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
State<FacebookLinkElementsComponent> createState() =>
|
||||
_FacebookLinkElementsComponentState();
|
||||
State<LinkElementsComponent> createState() => _LinkElementsComponentState();
|
||||
}
|
||||
|
||||
class _FacebookLinkElementsComponentState
|
||||
extends State<FacebookLinkElementsComponent> {
|
||||
class _LinkElementsComponentState extends State<LinkElementsComponent> {
|
||||
final previewWidth = 500.0;
|
||||
final previewHeight = 165.0;
|
||||
static final _logger = Logger('$_FacebookLinkElementsComponentState');
|
||||
static final _logger = Logger('$_LinkElementsComponentState');
|
||||
final _linkPreviewData = <Metadata>[];
|
||||
|
||||
@override
|
||||
|
@ -73,7 +71,7 @@ class _FacebookLinkElementsComponentState
|
|||
onPressed: () async {
|
||||
await canLaunch(l.url!)
|
||||
? await launch(l.url!)
|
||||
: FacebookLinkElementsComponent._logger
|
||||
: LinkElementsComponent._logger
|
||||
.info('Failed to launch ${l.url}');
|
||||
},
|
||||
child: _buildLinkPreview(context, l))),
|
|
@ -1,21 +1,20 @@
|
|||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_media_attachment.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/screens/facebook_media_slideshow_screen.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/friendica_media_attachment.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/screens/media_slideshow_screen.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/services/path_mapping_service.dart';
|
||||
import 'package:friendica_archive_browser/src/settings/settings_controller.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'facebook_media_wrapper_component.dart';
|
||||
import 'media_wrapper_component.dart';
|
||||
|
||||
class FacebookMediaTimelineComponent extends StatelessWidget {
|
||||
class MediaTimelineComponent extends StatelessWidget {
|
||||
static const double _maxHeightWidth = 400.0;
|
||||
|
||||
final List<FacebookMediaAttachment> mediaAttachments;
|
||||
final List<FriendicaMediaAttachment> mediaAttachments;
|
||||
|
||||
const FacebookMediaTimelineComponent(
|
||||
{Key? key, required this.mediaAttachments})
|
||||
const MediaTimelineComponent({Key? key, required this.mediaAttachments})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
|
@ -49,12 +48,12 @@ class FacebookMediaTimelineComponent extends StatelessWidget {
|
|||
ChangeNotifierProvider.value(value: settingsController),
|
||||
Provider.value(value: pathMapper)
|
||||
],
|
||||
child: FacebookMediaSlideshowScreen(
|
||||
child: MediaSlideShowScreen(
|
||||
mediaAttachments: mediaAttachments,
|
||||
initialIndex: index));
|
||||
}));
|
||||
},
|
||||
child: FacebookMediaWrapperComponent(
|
||||
child: MediaWrapperComponent(
|
||||
mediaAttachment: mediaAttachments[index],
|
||||
preferredWidth: isSingle ? singleWidth : preferredMultiWidth,
|
||||
),
|
|
@ -2,22 +2,22 @@ import 'dart:async';
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_media_attachment.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/friendica_media_attachment.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/services/path_mapping_service.dart';
|
||||
import 'package:friendica_archive_browser/src/settings/settings_controller.dart';
|
||||
import 'package:friendica_archive_browser/src/utils/snackbar_status_builder.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class FacebookMediaWrapperComponent extends StatelessWidget {
|
||||
static final _logger = Logger('$FacebookMediaWrapperComponent');
|
||||
class MediaWrapperComponent extends StatelessWidget {
|
||||
static final _logger = Logger('$MediaWrapperComponent');
|
||||
|
||||
static const double _noPreferredValue = -1.0;
|
||||
final FacebookMediaAttachment mediaAttachment;
|
||||
final FriendicaMediaAttachment mediaAttachment;
|
||||
final double preferredWidth;
|
||||
final double preferredHeight;
|
||||
|
||||
const FacebookMediaWrapperComponent(
|
||||
const MediaWrapperComponent(
|
||||
{Key? key,
|
||||
required this.mediaAttachment,
|
||||
this.preferredWidth = _noPreferredValue,
|
||||
|
@ -39,11 +39,11 @@ class FacebookMediaWrapperComponent extends StatelessWidget {
|
|||
: MediaQuery.of(context).size.height;
|
||||
|
||||
if (mediaAttachment.estimatedType() ==
|
||||
FacebookAttachmentMediaType.unknown) {
|
||||
FriendicaAttachmentMediaType.unknown) {
|
||||
return Text('Unable to resolve type for ${mediaAttachment.uri.path}');
|
||||
}
|
||||
|
||||
if (mediaAttachment.estimatedType() == FacebookAttachmentMediaType.video) {
|
||||
if (mediaAttachment.estimatedType() == FriendicaAttachmentMediaType.video) {
|
||||
final title = "Video (click to play): " + mediaAttachment.title;
|
||||
final thumbnailImageResult = _uriToImage(
|
||||
mediaAttachment.thumbnailUri, pathMapper,
|
||||
|
@ -75,7 +75,7 @@ class FacebookMediaWrapperComponent extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
|
||||
if (mediaAttachment.estimatedType() == FacebookAttachmentMediaType.image) {
|
||||
if (mediaAttachment.estimatedType() == FriendicaAttachmentMediaType.image) {
|
||||
final imageResult = _uriToImage(mediaAttachment.uri, pathMapper);
|
||||
if (imageResult.image == null) {
|
||||
final errorPath = imageResult.path.isNotEmpty
|
|
@ -1,18 +1,18 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_location_data.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_post.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_timeline_type.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/friendica_post.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/location_data.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/timeline_type.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/services/path_mapping_service.dart';
|
||||
import 'package:friendica_archive_browser/src/settings/settings_controller.dart';
|
||||
import 'package:friendica_archive_browser/src/utils/clipboard_helper.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'facebook_link_elements_component.dart';
|
||||
import 'facebook_media_timeline_component.dart';
|
||||
import 'link_elements_component.dart';
|
||||
import 'media_timeline_component.dart';
|
||||
|
||||
class PostCard extends StatelessWidget {
|
||||
final FacebookPost post;
|
||||
final FriendicaPost post;
|
||||
|
||||
const PostCard({Key? key, required this.post}) : super(key: key);
|
||||
|
||||
|
@ -53,14 +53,14 @@ class PostCard extends StatelessWidget {
|
|||
style: const TextStyle(
|
||||
fontStyle: FontStyle.italic,
|
||||
)),
|
||||
if (post.timelineType != FacebookTimelineType.active)
|
||||
if (post.timelineType != TimelineType.active)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 8.0),
|
||||
child: Tooltip(
|
||||
message:
|
||||
'Post is in ${post.timelineType == FacebookTimelineType.trash ? 'Trash' : 'Archive'}',
|
||||
'Post is in ${post.timelineType == TimelineType.trash ? 'Trash' : 'Archive'}',
|
||||
child: Icon(
|
||||
post.timelineType == FacebookTimelineType.trash
|
||||
post.timelineType == TimelineType.trash
|
||||
? Icons.delete_outline
|
||||
: Icons.archive_outlined,
|
||||
color: Theme.of(context).disabledColor,
|
||||
|
@ -84,12 +84,11 @@ class PostCard extends StatelessWidget {
|
|||
post.locationData.toWidget(spacingHeight),
|
||||
if (post.links.isNotEmpty) ...[
|
||||
const SizedBox(height: spacingHeight),
|
||||
FacebookLinkElementsComponent(links: post.links)
|
||||
LinkElementsComponent(links: post.links)
|
||||
],
|
||||
if (post.mediaAttachments.isNotEmpty) ...[
|
||||
const SizedBox(height: spacingHeight),
|
||||
FacebookMediaTimelineComponent(
|
||||
mediaAttachments: post.mediaAttachments)
|
||||
MediaTimelineComponent(mediaAttachments: post.mediaAttachments)
|
||||
]
|
||||
],
|
||||
),
|
||||
|
|
|
@ -1,101 +0,0 @@
|
|||
import 'package:logging/logging.dart';
|
||||
|
||||
import 'model_utils.dart';
|
||||
|
||||
class FacebookSavedItem {
|
||||
static final _logger = Logger('$FacebookSavedItem');
|
||||
final String externalName;
|
||||
final int timestamp;
|
||||
final String title;
|
||||
final String text;
|
||||
final Uri uri;
|
||||
|
||||
FacebookSavedItem(
|
||||
{this.externalName = '',
|
||||
this.timestamp = 0,
|
||||
this.title = '',
|
||||
this.text = '',
|
||||
required this.uri});
|
||||
|
||||
FacebookSavedItem copy(
|
||||
{String? externalName,
|
||||
int? timestamp,
|
||||
String? title,
|
||||
String? text,
|
||||
Uri? uri}) {
|
||||
return FacebookSavedItem(
|
||||
externalName: externalName ?? this.externalName,
|
||||
timestamp: timestamp ?? this.timestamp,
|
||||
title: title ?? this.title,
|
||||
text: text ?? this.text,
|
||||
uri: uri ?? this.uri,
|
||||
);
|
||||
}
|
||||
|
||||
static FacebookSavedItem fromFacebookJson(Map<String, dynamic> json) {
|
||||
final knownTopLevelKeys = ['attachments', 'title', 'timestamp'];
|
||||
final knownExternalContextKeys = ['name', 'source', 'url'];
|
||||
int timestamp = json['timestamp'] ?? 0;
|
||||
|
||||
logAdditionalKeys(knownTopLevelKeys, json.keys, _logger, Level.WARNING,
|
||||
'Unknown root key');
|
||||
|
||||
final title = json['title'] ?? '';
|
||||
var name = '';
|
||||
var linkUri = Uri.parse('');
|
||||
var externalName = '';
|
||||
|
||||
if (json.containsKey('attachments')) {
|
||||
final attachments = json['attachments'] ?? <Map<String, dynamic>>[];
|
||||
if (attachments.length > 1) {
|
||||
_logger.severe(
|
||||
'Saved item has multiple attachment items, will only use first: ${attachments.length}');
|
||||
}
|
||||
var found = false;
|
||||
for (Map<String, dynamic> attachment in attachments) {
|
||||
final dataItem = attachment['data'] ?? <Map<String, dynamic>>[];
|
||||
if (dataItem.length > 1) {
|
||||
_logger.severe(
|
||||
'Attachment has multiple data items, will only use first: ${dataItem.length}');
|
||||
}
|
||||
for (Map<String, dynamic> externalItem in dataItem) {
|
||||
logAdditionalKeys(['external_context'], externalItem.keys, _logger,
|
||||
Level.WARNING, 'Unknown external data item key');
|
||||
final externalData =
|
||||
externalItem['external_context'] ?? <String, String>{};
|
||||
logAdditionalKeys(knownExternalContextKeys, externalData.keys,
|
||||
_logger, Level.WARNING, 'Unknown external context key');
|
||||
|
||||
name = externalData['name'] ?? '';
|
||||
final source = externalData['source'] ?? '';
|
||||
final url = externalData['url'] ?? '';
|
||||
|
||||
final sourceUri = Uri.parse(source);
|
||||
final urlUri = Uri.parse(url);
|
||||
|
||||
if (sourceUri.scheme.startsWith('http')) {
|
||||
linkUri = sourceUri;
|
||||
externalName = url;
|
||||
} else {
|
||||
linkUri = urlUri;
|
||||
externalName = source;
|
||||
}
|
||||
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FacebookSavedItem(
|
||||
timestamp: timestamp,
|
||||
externalName: externalName,
|
||||
title: title,
|
||||
text: name,
|
||||
uri: linkUri);
|
||||
}
|
||||
}
|
|
@ -1,20 +1,20 @@
|
|||
import 'package:logging/logging.dart';
|
||||
|
||||
import 'facebook_comment.dart';
|
||||
import 'facebook_media_attachment.dart';
|
||||
import 'friendica_comment.dart';
|
||||
import 'friendica_media_attachment.dart';
|
||||
import 'model_utils.dart';
|
||||
|
||||
class FacebookAlbum {
|
||||
static final _logger = Logger('$FacebookAlbum');
|
||||
class FriendicaAlbum {
|
||||
static final _logger = Logger('$FriendicaAlbum');
|
||||
|
||||
final String name;
|
||||
final String description;
|
||||
final int lastModifiedTimestamp;
|
||||
final FacebookMediaAttachment coverPhoto;
|
||||
final List<FacebookMediaAttachment> photos;
|
||||
final List<FacebookComment> comments;
|
||||
final FriendicaMediaAttachment coverPhoto;
|
||||
final List<FriendicaMediaAttachment> photos;
|
||||
final List<FriendicaComment> comments;
|
||||
|
||||
FacebookAlbum(
|
||||
FriendicaAlbum(
|
||||
{required this.name,
|
||||
required this.description,
|
||||
required this.lastModifiedTimestamp,
|
||||
|
@ -22,7 +22,7 @@ class FacebookAlbum {
|
|||
required this.photos,
|
||||
required this.comments});
|
||||
|
||||
static FacebookAlbum fromJson(Map<String, dynamic> json) {
|
||||
static FriendicaAlbum fromJson(Map<String, dynamic> json) {
|
||||
final knownAlbumKeys = [
|
||||
'name',
|
||||
'photos',
|
||||
|
@ -38,21 +38,21 @@ class FacebookAlbum {
|
|||
String name = json['name'] ?? '';
|
||||
String description = json['description'] ?? '';
|
||||
int lastModifiedTimestamp = json['last_modified_timestamp'] ?? 0;
|
||||
FacebookMediaAttachment coverPhoto = json.containsKey('cover_photo')
|
||||
? FacebookMediaAttachment.fromFacebookJson(json['cover_photo'])
|
||||
: FacebookMediaAttachment.blank();
|
||||
FriendicaMediaAttachment coverPhoto = json.containsKey('cover_photo')
|
||||
? FriendicaMediaAttachment.fromFacebookJson(json['cover_photo'])
|
||||
: FriendicaMediaAttachment.blank();
|
||||
|
||||
final photos = <FacebookMediaAttachment>[];
|
||||
final photos = <FriendicaMediaAttachment>[];
|
||||
for (Map<String, dynamic> photoJson in json['photos'] ?? []) {
|
||||
photos.add(FacebookMediaAttachment.fromFacebookJson(photoJson));
|
||||
photos.add(FriendicaMediaAttachment.fromFacebookJson(photoJson));
|
||||
}
|
||||
|
||||
final comments = <FacebookComment>[];
|
||||
final comments = <FriendicaComment>[];
|
||||
for (Map<String, dynamic> commentsJson in json['comments'] ?? []) {
|
||||
comments.add(FacebookComment.fromInnerCommentJson(commentsJson));
|
||||
comments.add(FriendicaComment.fromInnerCommentJson(commentsJson));
|
||||
}
|
||||
|
||||
return FacebookAlbum(
|
||||
return FriendicaAlbum(
|
||||
name: name,
|
||||
description: description,
|
||||
lastModifiedTimestamp: lastModifiedTimestamp,
|
|
@ -2,11 +2,11 @@ import 'package:friendica_archive_browser/src/friendica/services/path_mapping_se
|
|||
import 'package:intl/intl.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
import 'facebook_media_attachment.dart';
|
||||
import 'friendica_media_attachment.dart';
|
||||
import 'model_utils.dart';
|
||||
|
||||
class FacebookComment {
|
||||
static final _logger = Logger('$FacebookComment');
|
||||
class FriendicaComment {
|
||||
static final _logger = Logger('$FriendicaComment');
|
||||
|
||||
final int creationTimestamp;
|
||||
|
||||
|
@ -18,22 +18,22 @@ class FacebookComment {
|
|||
|
||||
final String title;
|
||||
|
||||
final List<FacebookMediaAttachment> mediaAttachments;
|
||||
final List<FriendicaMediaAttachment> mediaAttachments;
|
||||
|
||||
final List<Uri> links;
|
||||
|
||||
FacebookComment(
|
||||
FriendicaComment(
|
||||
{this.creationTimestamp = 0,
|
||||
this.author = '',
|
||||
this.comment = '',
|
||||
this.group = '',
|
||||
this.title = '',
|
||||
List<FacebookMediaAttachment>? mediaAttachments,
|
||||
List<FriendicaMediaAttachment>? mediaAttachments,
|
||||
List<Uri>? links})
|
||||
: mediaAttachments = mediaAttachments ?? <FacebookMediaAttachment>[],
|
||||
: mediaAttachments = mediaAttachments ?? <FriendicaMediaAttachment>[],
|
||||
links = links ?? <Uri>[];
|
||||
|
||||
FacebookComment.randomBuilt()
|
||||
FriendicaComment.randomBuilt()
|
||||
: creationTimestamp = DateTime.now().millisecondsSinceEpoch,
|
||||
author = 'Random Author ${randomId()}',
|
||||
comment = 'Random comment text ${randomId()}',
|
||||
|
@ -44,19 +44,19 @@ class FacebookComment {
|
|||
Uri.parse('http://localhost/${randomId()}')
|
||||
],
|
||||
mediaAttachments = [
|
||||
FacebookMediaAttachment.randomBuilt(),
|
||||
FacebookMediaAttachment.randomBuilt()
|
||||
FriendicaMediaAttachment.randomBuilt(),
|
||||
FriendicaMediaAttachment.randomBuilt()
|
||||
];
|
||||
|
||||
FacebookComment copy(
|
||||
FriendicaComment copy(
|
||||
{int? creationTimestamp,
|
||||
String? author,
|
||||
String? comment,
|
||||
String? group,
|
||||
String? title,
|
||||
List<FacebookMediaAttachment>? mediaAttachments,
|
||||
List<FriendicaMediaAttachment>? mediaAttachments,
|
||||
List<Uri>? links}) {
|
||||
return FacebookComment(
|
||||
return FriendicaComment(
|
||||
creationTimestamp: creationTimestamp ?? this.creationTimestamp,
|
||||
author: author ?? this.author,
|
||||
comment: comment ?? this.comment,
|
||||
|
@ -90,14 +90,14 @@ class FacebookComment {
|
|||
].join('\n');
|
||||
}
|
||||
|
||||
FacebookComment.fromJson(Map<String, dynamic> json)
|
||||
FriendicaComment.fromJson(Map<String, dynamic> json)
|
||||
: creationTimestamp = json['creationTimeStamp'] ?? 0,
|
||||
author = json['author'] ?? '',
|
||||
comment = json['comment'] ?? '',
|
||||
group = json['group'] ?? '',
|
||||
title = json['title'] ?? '',
|
||||
mediaAttachments = (json['mediaAttachments'] as List<dynamic>? ?? [])
|
||||
.map((j) => FacebookMediaAttachment.fromJson(j))
|
||||
.map((j) => FriendicaMediaAttachment.fromJson(j))
|
||||
.toList(),
|
||||
links = (json['links'] as List<dynamic>? ?? [])
|
||||
.map((j) => Uri.parse(j))
|
||||
|
@ -115,15 +115,15 @@ class FacebookComment {
|
|||
|
||||
bool hasImages() => mediaAttachments
|
||||
.where((element) =>
|
||||
element.estimatedType() == FacebookAttachmentMediaType.image)
|
||||
element.estimatedType() == FriendicaAttachmentMediaType.image)
|
||||
.isNotEmpty;
|
||||
|
||||
bool hasVideos() => mediaAttachments
|
||||
.where((element) =>
|
||||
element.estimatedType() == FacebookAttachmentMediaType.video)
|
||||
element.estimatedType() == FriendicaAttachmentMediaType.video)
|
||||
.isNotEmpty;
|
||||
|
||||
static FacebookComment fromInnerCommentJson(
|
||||
static FriendicaComment fromInnerCommentJson(
|
||||
Map<String, dynamic> commentSubData) {
|
||||
final knownCommentKeys = ['comment', 'timestamp', 'group', 'author'];
|
||||
if (_logger.isLoggable(Level.WARNING)) {
|
||||
|
@ -135,7 +135,7 @@ class FacebookComment {
|
|||
final author = commentSubData['author'] ?? '';
|
||||
final timestamp = commentSubData['timestamp'] ?? 0;
|
||||
|
||||
return FacebookComment(
|
||||
return FriendicaComment(
|
||||
creationTimestamp: timestamp,
|
||||
author: author,
|
||||
group: group,
|
||||
|
@ -143,7 +143,7 @@ class FacebookComment {
|
|||
);
|
||||
}
|
||||
|
||||
static FacebookComment fromFacebookJson(Map<String, dynamic> json) {
|
||||
static FriendicaComment fromFacebookJson(Map<String, dynamic> json) {
|
||||
final knownTopLevelKeys = ['timestamp', 'data', 'title', 'attachments'];
|
||||
final knownExternalContextKeys = ['external_context', 'media', 'name'];
|
||||
int timestamp = json['timestamp'] ?? 0;
|
||||
|
@ -151,13 +151,13 @@ class FacebookComment {
|
|||
logAdditionalKeys(knownTopLevelKeys, json.keys, _logger, Level.WARNING,
|
||||
'Unknown top level comment keys');
|
||||
|
||||
FacebookComment basicCommentData = FacebookComment();
|
||||
FriendicaComment basicCommentData = FriendicaComment();
|
||||
if (json.containsKey('data')) {
|
||||
final data = json['data'];
|
||||
for (var dataItem in data) {
|
||||
if (dataItem.containsKey('comment')) {
|
||||
basicCommentData =
|
||||
FacebookComment.fromInnerCommentJson(dataItem['comment']);
|
||||
FriendicaComment.fromInnerCommentJson(dataItem['comment']);
|
||||
} else {
|
||||
_logger.warning(
|
||||
"No comment or update key sequence in post @$timestamp: ${dataItem.keys}");
|
||||
|
@ -167,7 +167,7 @@ class FacebookComment {
|
|||
|
||||
final String title = json['title'] ?? '';
|
||||
final links = <Uri>[];
|
||||
final mediaAttachments = <FacebookMediaAttachment>[];
|
||||
final mediaAttachments = <FriendicaMediaAttachment>[];
|
||||
|
||||
if (json.containsKey('attachments')) {
|
||||
for (Map<String, dynamic> attachment in json['attachments']) {
|
||||
|
@ -191,13 +191,13 @@ class FacebookComment {
|
|||
}
|
||||
} else if (dataItem.containsKey('media')) {
|
||||
mediaAttachments.add(
|
||||
FacebookMediaAttachment.fromFacebookJson(dataItem['media']));
|
||||
FriendicaMediaAttachment.fromFacebookJson(dataItem['media']));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FacebookComment(
|
||||
return FriendicaComment(
|
||||
creationTimestamp: timestamp,
|
||||
author: basicCommentData.author,
|
||||
comment: basicCommentData.comment,
|
|
@ -2,8 +2,8 @@ import 'package:logging/logging.dart';
|
|||
|
||||
import 'model_utils.dart';
|
||||
|
||||
class FacebookFriend {
|
||||
static final _logger = Logger('$FacebookFriend');
|
||||
class FriendicaContact {
|
||||
static final _logger = Logger('$FriendicaContact');
|
||||
|
||||
final FriendStatus status;
|
||||
final String name;
|
||||
|
@ -15,7 +15,7 @@ class FacebookFriend {
|
|||
final int sentTimestamp;
|
||||
final bool markedAsSpam;
|
||||
|
||||
FacebookFriend(
|
||||
FriendicaContact(
|
||||
{this.status = FriendStatus.unknown,
|
||||
required this.name,
|
||||
this.contactInfo = '',
|
||||
|
@ -31,7 +31,7 @@ class FacebookFriend {
|
|||
return 'FacebookFriend{status: $status, name: $name, contactInfo: $contactInfo, friendSinceTimestamp: $friendSinceTimestamp, receivedTimestamp: $receivedTimestamp, rejectedTimestamp: $rejectedTimestamp, removeTimestamp: $removeTimestamp, sentTimestamp: $sentTimestamp, markedAsSpam: $markedAsSpam}';
|
||||
}
|
||||
|
||||
static FacebookFriend fromJson(
|
||||
static FriendicaContact fromJson(
|
||||
Map<String, dynamic> json, FriendStatus status) {
|
||||
final knownTopLevelKeys = [
|
||||
'timestamp',
|
||||
|
@ -49,42 +49,42 @@ class FacebookFriend {
|
|||
|
||||
switch (status) {
|
||||
case FriendStatus.friends:
|
||||
return FacebookFriend(
|
||||
return FriendicaContact(
|
||||
name: name,
|
||||
status: status,
|
||||
contactInfo: contactInfo,
|
||||
markedAsSpam: markedAsSpam,
|
||||
friendSinceTimestamp: timestamp);
|
||||
case FriendStatus.requestReceived:
|
||||
return FacebookFriend(
|
||||
return FriendicaContact(
|
||||
name: name,
|
||||
status: status,
|
||||
contactInfo: contactInfo,
|
||||
markedAsSpam: markedAsSpam,
|
||||
receivedTimestamp: timestamp);
|
||||
case FriendStatus.rejectedRequest:
|
||||
return FacebookFriend(
|
||||
return FriendicaContact(
|
||||
name: name,
|
||||
status: status,
|
||||
contactInfo: contactInfo,
|
||||
markedAsSpam: markedAsSpam,
|
||||
rejectedTimestamp: timestamp);
|
||||
case FriendStatus.removed:
|
||||
return FacebookFriend(
|
||||
return FriendicaContact(
|
||||
name: name,
|
||||
status: status,
|
||||
contactInfo: contactInfo,
|
||||
markedAsSpam: markedAsSpam,
|
||||
removeTimestamp: timestamp);
|
||||
case FriendStatus.sentFriendRequest:
|
||||
return FacebookFriend(
|
||||
return FriendicaContact(
|
||||
name: name,
|
||||
status: status,
|
||||
contactInfo: contactInfo,
|
||||
markedAsSpam: markedAsSpam,
|
||||
sentTimestamp: timestamp);
|
||||
case FriendStatus.unknown:
|
||||
return FacebookFriend(
|
||||
return FriendicaContact(
|
||||
name: name,
|
||||
status: status,
|
||||
contactInfo: contactInfo,
|
|
@ -3,13 +3,13 @@ import 'dart:io';
|
|||
import 'package:friendica_archive_browser/src/friendica/services/path_mapping_service.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
import 'facebook_comment.dart';
|
||||
import 'friendica_comment.dart';
|
||||
import 'model_utils.dart';
|
||||
|
||||
enum FacebookAttachmentMediaType { unknown, image, video }
|
||||
enum FriendicaAttachmentMediaType { unknown, image, video }
|
||||
|
||||
class FacebookMediaAttachment {
|
||||
static final _logger = Logger('$FacebookMediaAttachment');
|
||||
class FriendicaMediaAttachment {
|
||||
static final _logger = Logger('$FriendicaMediaAttachment');
|
||||
static final _graphicsExtensions = ['jpg', 'png', 'gif', 'tif'];
|
||||
static final _movieExtensions = ['avi', 'mp4', 'mpg', 'wmv'];
|
||||
|
||||
|
@ -19,7 +19,7 @@ class FacebookMediaAttachment {
|
|||
|
||||
final Map<String, String> metadata;
|
||||
|
||||
final List<FacebookComment> comments;
|
||||
final List<FriendicaComment> comments;
|
||||
|
||||
final Uri thumbnailUri;
|
||||
|
||||
|
@ -27,7 +27,7 @@ class FacebookMediaAttachment {
|
|||
|
||||
final String description;
|
||||
|
||||
FacebookMediaAttachment(
|
||||
FriendicaMediaAttachment(
|
||||
{required this.uri,
|
||||
required this.creationTimestamp,
|
||||
required this.metadata,
|
||||
|
@ -36,19 +36,19 @@ class FacebookMediaAttachment {
|
|||
required this.description,
|
||||
required this.comments});
|
||||
|
||||
FacebookMediaAttachment.randomBuilt()
|
||||
FriendicaMediaAttachment.randomBuilt()
|
||||
: uri = Uri.parse('http://localhost/${randomId()}'),
|
||||
creationTimestamp = DateTime.now().millisecondsSinceEpoch,
|
||||
title = 'Random title ${randomId()}',
|
||||
thumbnailUri = Uri.parse('${randomId()}.jpg'),
|
||||
description = 'Random description ${randomId()}',
|
||||
comments = [
|
||||
FacebookComment.randomBuilt(),
|
||||
FacebookComment.randomBuilt()
|
||||
FriendicaComment.randomBuilt(),
|
||||
FriendicaComment.randomBuilt()
|
||||
],
|
||||
metadata = {'value1': randomId(), 'value2': randomId()};
|
||||
|
||||
FacebookMediaAttachment.fromUriOnly(this.uri)
|
||||
FriendicaMediaAttachment.fromUriOnly(this.uri)
|
||||
: creationTimestamp = 0,
|
||||
thumbnailUri = Uri.file(''),
|
||||
title = '',
|
||||
|
@ -56,14 +56,14 @@ class FacebookMediaAttachment {
|
|||
comments = [],
|
||||
metadata = {};
|
||||
|
||||
FacebookMediaAttachment.fromUriAndTime(this.uri, this.creationTimestamp)
|
||||
FriendicaMediaAttachment.fromUriAndTime(this.uri, this.creationTimestamp)
|
||||
: thumbnailUri = Uri.file(''),
|
||||
title = '',
|
||||
description = '',
|
||||
comments = [],
|
||||
metadata = {};
|
||||
|
||||
FacebookMediaAttachment.blank()
|
||||
FriendicaMediaAttachment.blank()
|
||||
: uri = Uri(),
|
||||
creationTimestamp = 0,
|
||||
thumbnailUri = Uri.file(''),
|
||||
|
@ -85,15 +85,15 @@ class FacebookMediaAttachment {
|
|||
return mapper.toFullPath(uri.toString());
|
||||
}
|
||||
|
||||
FacebookAttachmentMediaType estimatedType() => mediaTypeFromString(uri.path);
|
||||
FriendicaAttachmentMediaType estimatedType() => mediaTypeFromString(uri.path);
|
||||
|
||||
FacebookMediaAttachment.fromJson(Map<String, dynamic> json)
|
||||
FriendicaMediaAttachment.fromJson(Map<String, dynamic> json)
|
||||
: uri = Uri.parse(json['uri']),
|
||||
creationTimestamp = json['creationTimestamp'],
|
||||
metadata = (json['metadata'] as Map<String, dynamic>? ?? {})
|
||||
.map((key, value) => MapEntry(key, value.toString())),
|
||||
comments = (json['comments'] as List<dynamic>? ?? [])
|
||||
.map((j) => FacebookComment.fromJson(j))
|
||||
.map((j) => FriendicaComment.fromJson(j))
|
||||
.toList(),
|
||||
thumbnailUri = Uri.parse(json['thumbnailUri'] ?? ''),
|
||||
title = json['title'] ?? '',
|
||||
|
@ -109,7 +109,7 @@ class FacebookMediaAttachment {
|
|||
'description': description,
|
||||
};
|
||||
|
||||
static FacebookMediaAttachment fromFacebookJson(Map<String, dynamic> json) {
|
||||
static FriendicaMediaAttachment fromFacebookJson(Map<String, dynamic> json) {
|
||||
final Uri uri = Uri.parse(json['uri']);
|
||||
final int timestamp = json['creation_timestamp'] ?? 0;
|
||||
final String title = json['title'] ?? '';
|
||||
|
@ -130,13 +130,13 @@ class FacebookMediaAttachment {
|
|||
metadata[key] = value;
|
||||
}
|
||||
});
|
||||
final comments = <FacebookComment>[];
|
||||
final comments = <FriendicaComment>[];
|
||||
for (Map<String, dynamic> commentJson in json['comments'] ?? {}) {
|
||||
final comment = FacebookComment.fromInnerCommentJson(commentJson);
|
||||
final comment = FriendicaComment.fromInnerCommentJson(commentJson);
|
||||
comments.add(comment);
|
||||
}
|
||||
|
||||
return FacebookMediaAttachment(
|
||||
return FriendicaMediaAttachment(
|
||||
uri: uri,
|
||||
creationTimestamp: timestamp,
|
||||
metadata: metadata,
|
||||
|
@ -146,25 +146,25 @@ class FacebookMediaAttachment {
|
|||
description: description);
|
||||
}
|
||||
|
||||
static FacebookAttachmentMediaType mediaTypeFromString(String path) {
|
||||
static FriendicaAttachmentMediaType mediaTypeFromString(String path) {
|
||||
final separator = Platform.isWindows ? '\\' : '/';
|
||||
final lastSlash = path.lastIndexOf(separator) + 1;
|
||||
final filename = path.substring(lastSlash);
|
||||
final lastPeriod = filename.lastIndexOf('.') + 1;
|
||||
if (lastPeriod == 0) {
|
||||
return FacebookAttachmentMediaType.unknown;
|
||||
return FriendicaAttachmentMediaType.unknown;
|
||||
}
|
||||
|
||||
final extension = filename.substring(lastPeriod).toLowerCase();
|
||||
|
||||
if (_graphicsExtensions.contains(extension)) {
|
||||
return FacebookAttachmentMediaType.image;
|
||||
return FriendicaAttachmentMediaType.image;
|
||||
}
|
||||
|
||||
if (_movieExtensions.contains(extension)) {
|
||||
return FacebookAttachmentMediaType.video;
|
||||
return FriendicaAttachmentMediaType.video;
|
||||
}
|
||||
|
||||
return FacebookAttachmentMediaType.unknown;
|
||||
return FriendicaAttachmentMediaType.unknown;
|
||||
}
|
||||
}
|
|
@ -2,13 +2,13 @@ import 'package:friendica_archive_browser/src/friendica/services/path_mapping_se
|
|||
import 'package:intl/intl.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
import 'facebook_location_data.dart';
|
||||
import 'facebook_media_attachment.dart';
|
||||
import 'facebook_timeline_type.dart';
|
||||
import 'friendica_media_attachment.dart';
|
||||
import 'location_data.dart';
|
||||
import 'model_utils.dart';
|
||||
import 'timeline_type.dart';
|
||||
|
||||
class FacebookPost {
|
||||
static final _logger = Logger('$FacebookPost');
|
||||
class FriendicaPost {
|
||||
static final _logger = Logger('$FriendicaPost');
|
||||
|
||||
final int creationTimestamp;
|
||||
|
||||
|
@ -20,55 +20,55 @@ class FacebookPost {
|
|||
|
||||
final String title;
|
||||
|
||||
final List<FacebookMediaAttachment> mediaAttachments;
|
||||
final List<FriendicaMediaAttachment> mediaAttachments;
|
||||
|
||||
final FacebookLocationData locationData;
|
||||
final LocationData locationData;
|
||||
|
||||
final List<Uri> links;
|
||||
|
||||
final FacebookTimelineType timelineType;
|
||||
final TimelineType timelineType;
|
||||
|
||||
FacebookPost(
|
||||
FriendicaPost(
|
||||
{this.creationTimestamp = 0,
|
||||
this.backdatedTimestamp = 0,
|
||||
this.modificationTimestamp = 0,
|
||||
this.post = '',
|
||||
this.title = '',
|
||||
this.locationData = const FacebookLocationData(),
|
||||
this.locationData = const LocationData(),
|
||||
required this.timelineType,
|
||||
List<FacebookMediaAttachment>? mediaAttachments,
|
||||
List<FriendicaMediaAttachment>? mediaAttachments,
|
||||
List<Uri>? links})
|
||||
: mediaAttachments = mediaAttachments ?? <FacebookMediaAttachment>[],
|
||||
: mediaAttachments = mediaAttachments ?? <FriendicaMediaAttachment>[],
|
||||
links = links ?? <Uri>[];
|
||||
|
||||
FacebookPost.randomBuilt()
|
||||
FriendicaPost.randomBuilt()
|
||||
: creationTimestamp = DateTime.now().millisecondsSinceEpoch,
|
||||
backdatedTimestamp = DateTime.now().millisecondsSinceEpoch,
|
||||
modificationTimestamp = DateTime.now().millisecondsSinceEpoch,
|
||||
post = 'Random post text ${randomId()}',
|
||||
title = 'Random title ${randomId()}',
|
||||
locationData = FacebookLocationData.randomBuilt(),
|
||||
timelineType = FacebookTimelineType.active,
|
||||
locationData = LocationData.randomBuilt(),
|
||||
timelineType = TimelineType.active,
|
||||
links = [
|
||||
Uri.parse('http://localhost/${randomId()}'),
|
||||
Uri.parse('http://localhost/${randomId()}')
|
||||
],
|
||||
mediaAttachments = [
|
||||
FacebookMediaAttachment.randomBuilt(),
|
||||
FacebookMediaAttachment.randomBuilt()
|
||||
FriendicaMediaAttachment.randomBuilt(),
|
||||
FriendicaMediaAttachment.randomBuilt()
|
||||
];
|
||||
|
||||
FacebookPost copy(
|
||||
FriendicaPost copy(
|
||||
{int? creationTimestamp,
|
||||
int? backdatedTimestamp,
|
||||
int? modificationTimestamp,
|
||||
String? post,
|
||||
String? title,
|
||||
FacebookLocationData? locationData,
|
||||
List<FacebookMediaAttachment>? mediaAttachments,
|
||||
FacebookTimelineType? timelineType,
|
||||
LocationData? locationData,
|
||||
List<FriendicaMediaAttachment>? mediaAttachments,
|
||||
TimelineType? timelineType,
|
||||
List<Uri>? links}) {
|
||||
return FacebookPost(
|
||||
return FriendicaPost(
|
||||
creationTimestamp: creationTimestamp ?? this.creationTimestamp,
|
||||
backdatedTimestamp: backdatedTimestamp ?? this.backdatedTimestamp,
|
||||
modificationTimestamp:
|
||||
|
@ -107,20 +107,20 @@ class FacebookPost {
|
|||
|
||||
bool hasImages() => mediaAttachments
|
||||
.where((element) =>
|
||||
element.estimatedType() == FacebookAttachmentMediaType.image)
|
||||
element.estimatedType() == FriendicaAttachmentMediaType.image)
|
||||
.isNotEmpty;
|
||||
|
||||
bool hasVideos() => mediaAttachments
|
||||
.where((element) =>
|
||||
element.estimatedType() == FacebookAttachmentMediaType.video)
|
||||
element.estimatedType() == FriendicaAttachmentMediaType.video)
|
||||
.isNotEmpty;
|
||||
|
||||
static FacebookPost fromJson(
|
||||
Map<String, dynamic> json, FacebookTimelineType timelineType) {
|
||||
static FriendicaPost fromJson(
|
||||
Map<String, dynamic> json, TimelineType timelineType) {
|
||||
final int timestamp = json['timestamp'] ?? 0;
|
||||
var modificationTimestamp = timestamp;
|
||||
var backdatedTimestamp = timestamp;
|
||||
var locationData = const FacebookLocationData();
|
||||
var locationData = const LocationData();
|
||||
String post = '';
|
||||
if (json.containsKey('data')) {
|
||||
final data = json['data'];
|
||||
|
@ -140,7 +140,7 @@ class FacebookPost {
|
|||
|
||||
final String title = json['title'] ?? '';
|
||||
final links = <Uri>[];
|
||||
final mediaAttachments = <FacebookMediaAttachment>[];
|
||||
final mediaAttachments = <FriendicaMediaAttachment>[];
|
||||
|
||||
if (json.containsKey('attachments')) {
|
||||
for (Map<String, dynamic> attachment in json['attachments']) {
|
||||
|
@ -156,9 +156,9 @@ class FacebookPost {
|
|||
}
|
||||
} else if (dataItem.containsKey('media')) {
|
||||
mediaAttachments.add(
|
||||
FacebookMediaAttachment.fromFacebookJson(dataItem['media']));
|
||||
FriendicaMediaAttachment.fromFacebookJson(dataItem['media']));
|
||||
} else if (dataItem.containsKey('place')) {
|
||||
locationData = FacebookLocationData.fromJson(dataItem['place']);
|
||||
locationData = LocationData.fromJson(dataItem['place']);
|
||||
} else {
|
||||
//TODO Add Facebook Post Poll Processing
|
||||
if (dataItem.containsKey('poll')) continue;
|
||||
|
@ -175,7 +175,7 @@ class FacebookPost {
|
|||
}
|
||||
}
|
||||
|
||||
late final FacebookLocationData actualLocationData;
|
||||
late final LocationData actualLocationData;
|
||||
if (locationData.hasPosition) {
|
||||
actualLocationData = locationData;
|
||||
} else {
|
||||
|
@ -186,7 +186,7 @@ class FacebookPost {
|
|||
final metadata = mediaWithPosition.first.metadata;
|
||||
final latitude = double.tryParse(metadata['latitude'] ?? '') ?? 0.0;
|
||||
final longitude = double.tryParse(metadata['longitude'] ?? '') ?? 0.0;
|
||||
actualLocationData = FacebookLocationData(
|
||||
actualLocationData = LocationData(
|
||||
latitude: latitude, longitude: longitude, hasPosition: true);
|
||||
} else {
|
||||
actualLocationData = locationData;
|
||||
|
@ -199,7 +199,7 @@ class FacebookPost {
|
|||
.map((m) => m.title)
|
||||
.firstWhere((t) => t.isNotEmpty, orElse: () => '');
|
||||
|
||||
return FacebookPost(
|
||||
return FriendicaPost(
|
||||
creationTimestamp: timestamp,
|
||||
modificationTimestamp: modificationTimestamp,
|
||||
backdatedTimestamp: backdatedTimestamp,
|
|
@ -1,11 +1,11 @@
|
|||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/components/facebook_link_elements_component.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/components/link_elements_component.dart';
|
||||
|
||||
import 'model_utils.dart';
|
||||
|
||||
class FacebookLocationData {
|
||||
class LocationData {
|
||||
final String name;
|
||||
|
||||
final double latitude;
|
||||
|
@ -20,7 +20,7 @@ class FacebookLocationData {
|
|||
|
||||
final String url;
|
||||
|
||||
const FacebookLocationData(
|
||||
const LocationData(
|
||||
{this.name = '',
|
||||
this.latitude = 0.0,
|
||||
this.longitude = 0.0,
|
||||
|
@ -29,7 +29,7 @@ class FacebookLocationData {
|
|||
this.address = '',
|
||||
this.url = ''});
|
||||
|
||||
FacebookLocationData.randomBuilt()
|
||||
LocationData.randomBuilt()
|
||||
: name = 'Location name ${randomId()}',
|
||||
latitude = Random().nextDouble(),
|
||||
longitude = Random().nextDouble(),
|
||||
|
@ -59,7 +59,7 @@ class FacebookLocationData {
|
|||
bool hasData() =>
|
||||
name.isNotEmpty || address.isNotEmpty || url.isNotEmpty || hasPosition;
|
||||
|
||||
static FacebookLocationData fromJson(Map<String, dynamic> json) {
|
||||
static LocationData fromJson(Map<String, dynamic> json) {
|
||||
final name = json['name'] ?? '';
|
||||
final address = json['address'] ?? '';
|
||||
final url = json['url'] ?? '';
|
||||
|
@ -74,7 +74,7 @@ class FacebookLocationData {
|
|||
altitude = position['altitude'] ?? 0.0;
|
||||
}
|
||||
|
||||
return FacebookLocationData(
|
||||
return LocationData(
|
||||
name: name,
|
||||
address: address,
|
||||
url: url,
|
||||
|
@ -85,7 +85,7 @@ class FacebookLocationData {
|
|||
}
|
||||
}
|
||||
|
||||
extension WidgetExtensions on FacebookLocationData {
|
||||
extension WidgetExtensions on LocationData {
|
||||
Widget toWidget(double spacingHeight) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
|
@ -110,7 +110,7 @@ extension WidgetExtensions on FacebookLocationData {
|
|||
],
|
||||
if (url.isNotEmpty) ...[
|
||||
SizedBox(height: spacingHeight),
|
||||
FacebookLinkElementsComponent(
|
||||
LinkElementsComponent(
|
||||
links: [Uri.parse(url)],
|
||||
),
|
||||
],
|
|
@ -1,4 +1,4 @@
|
|||
enum FacebookTimelineType {
|
||||
enum TimelineType {
|
||||
active,
|
||||
archive,
|
||||
trash,
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/components/comment_card.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/components/filter_control_component.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_comment.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/friendica_comment.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/model_utils.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/services/facebook_archive_service.dart';
|
||||
import 'package:friendica_archive_browser/src/screens/error_screen.dart';
|
||||
|
@ -14,10 +14,10 @@ import 'package:result_monad/result_monad.dart';
|
|||
import '../../screens/loading_status_screen.dart';
|
||||
import '../../screens/standin_status_screen.dart';
|
||||
|
||||
class FacebookCommentsScreen extends StatelessWidget {
|
||||
static final _logger = Logger('$FacebookCommentsScreen');
|
||||
class CommentsScreen extends StatelessWidget {
|
||||
static final _logger = Logger('$CommentsScreen');
|
||||
|
||||
const FacebookCommentsScreen({Key? key}) : super(key: key);
|
||||
const CommentsScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -26,7 +26,7 @@ class FacebookCommentsScreen extends StatelessWidget {
|
|||
|
||||
_logger.fine('Build FacebookPostListView');
|
||||
|
||||
return FutureBuilder<Result<List<FacebookComment>, ExecError>>(
|
||||
return FutureBuilder<Result<List<FriendicaComment>, ExecError>>(
|
||||
future: service.getComments(),
|
||||
builder: (context, snapshot) {
|
||||
_logger.fine('Future Comment builder called');
|
||||
|
@ -55,7 +55,7 @@ class FacebookCommentsScreen extends StatelessWidget {
|
|||
|
||||
class _FacebookCommentsScreenWidget extends StatelessWidget {
|
||||
static final _logger = Logger('$_FacebookCommentsScreenWidget');
|
||||
final List<FacebookComment> comments;
|
||||
final List<FriendicaComment> comments;
|
||||
final String username;
|
||||
|
||||
const _FacebookCommentsScreenWidget(
|
||||
|
@ -65,7 +65,7 @@ class _FacebookCommentsScreenWidget extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_logger.fine('Redrawing');
|
||||
return FilterControl<FacebookComment, dynamic>(
|
||||
return FilterControl<FriendicaComment, dynamic>(
|
||||
allItems: comments,
|
||||
imagesOnlyFilterFunction: (comment) => comment.hasImages(),
|
||||
videosOnlyFilterFunction: (comment) => comment.hasVideos(),
|
|
@ -1,136 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/components/filter_control_component.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/components/post_card.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_post.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_saved_item.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_timeline_type.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/model_utils.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/services/facebook_archive_service.dart';
|
||||
import 'package:friendica_archive_browser/src/screens/error_screen.dart';
|
||||
import 'package:friendica_archive_browser/src/settings/settings_controller.dart';
|
||||
import 'package:friendica_archive_browser/src/utils/exec_error.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:result_monad/result_monad.dart';
|
||||
|
||||
import '../../screens/loading_status_screen.dart';
|
||||
import '../../screens/standin_status_screen.dart';
|
||||
|
||||
class FacebookSavedItemsScreen extends StatelessWidget {
|
||||
static final _logger = Logger('$FacebookSavedItemsScreen');
|
||||
|
||||
const FacebookSavedItemsScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_logger.info('Build FacebookSavedItemsScreen');
|
||||
final service = Provider.of<FacebookArchiveDataService>(context);
|
||||
final username = Provider.of<SettingsController>(context).facebookName;
|
||||
|
||||
return FutureBuilder<Result<List<FacebookSavedItem>, ExecError>>(
|
||||
future: service.getSavedItems(),
|
||||
builder: (context, snapshot) {
|
||||
_logger.info('FacebookSavedItemsScreen Future builder called');
|
||||
|
||||
if (!snapshot.hasData ||
|
||||
snapshot.connectionState != ConnectionState.done) {
|
||||
return const LoadingStatusScreen(title: 'Loading savedItems');
|
||||
}
|
||||
|
||||
final savedItemsResult = snapshot.requireData;
|
||||
|
||||
if (savedItemsResult.isFailure) {
|
||||
return ErrorScreen(
|
||||
title: 'Error getting saved items',
|
||||
error: savedItemsResult.error);
|
||||
}
|
||||
|
||||
final allSavedItems = savedItemsResult.value;
|
||||
|
||||
final savedItems = username.isEmpty
|
||||
? allSavedItems.toList()
|
||||
: allSavedItems.map((item) {
|
||||
var newTitle = item.title;
|
||||
if (item.title == username) {
|
||||
newTitle = 'You posted';
|
||||
} else {
|
||||
newTitle = item.title
|
||||
.replaceAll(username, 'You')
|
||||
.replaceAll(wholeWordRegEx('his'), 'your')
|
||||
.replaceAll(wholeWordRegEx('her'), 'your');
|
||||
}
|
||||
if (newTitle == item.title) {
|
||||
return item;
|
||||
} else {
|
||||
return item.copy(title: newTitle);
|
||||
}
|
||||
}).toList();
|
||||
if (savedItems.isEmpty) {
|
||||
return const StandInStatusScreen(
|
||||
title: 'No saved items were found');
|
||||
}
|
||||
|
||||
_logger.fine('Build Saved Items ListView');
|
||||
final savedItemsAsPosts = savedItems
|
||||
.map((item) => FacebookPost(
|
||||
creationTimestamp: item.timestamp,
|
||||
title: item.title,
|
||||
post: item.text,
|
||||
links: item.uri.toString().isNotEmpty ? [item.uri] : [],
|
||||
timelineType: FacebookTimelineType.active))
|
||||
.toList();
|
||||
return _FacebookSavedItemsScreenWidget(
|
||||
savedItemsAsPosts: savedItemsAsPosts);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class _FacebookSavedItemsScreenWidget extends StatelessWidget {
|
||||
static final _logger = Logger('$_FacebookSavedItemsScreenWidget');
|
||||
|
||||
final List<FacebookPost> savedItemsAsPosts;
|
||||
|
||||
const _FacebookSavedItemsScreenWidget(
|
||||
{Key? key, required this.savedItemsAsPosts})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_logger.fine('Redrawing');
|
||||
return FilterControl<FacebookPost, dynamic>(
|
||||
allItems: savedItemsAsPosts,
|
||||
textSearchFilterFunction: (post, text) =>
|
||||
post.title.contains(text) ||
|
||||
post.post.contains(text) ||
|
||||
post.links.where((l) => l.toString().contains(text)).isNotEmpty,
|
||||
itemToDateTimeFunction: (post) =>
|
||||
DateTime.fromMillisecondsSinceEpoch(post.creationTimestamp * 1000),
|
||||
dateRangeFilterFunction: (post, start, stop) =>
|
||||
timestampInRange(post.creationTimestamp * 1000, start, stop),
|
||||
builder: (context, items) {
|
||||
if (items.isEmpty) {
|
||||
return const StandInStatusScreen(
|
||||
title: 'No saved items meet filter criteria');
|
||||
}
|
||||
|
||||
return ScrollConfiguration(
|
||||
behavior:
|
||||
ScrollConfiguration.of(context).copyWith(scrollbars: false),
|
||||
child: ListView.separated(
|
||||
primary: false,
|
||||
restorationId: 'facebookSavedItemsListView',
|
||||
itemCount: items.length,
|
||||
itemBuilder: (context, index) {
|
||||
_logger.finer('Rendering Saved Item List Item');
|
||||
return PostCard(post: items[index]);
|
||||
},
|
||||
separatorBuilder: (context, index) {
|
||||
return const Divider(
|
||||
color: Colors.black,
|
||||
thickness: 0.2,
|
||||
);
|
||||
}),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/components/filter_control_component.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/components/post_card.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_media_attachment.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_post.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/model_utils.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/services/facebook_archive_service.dart';
|
||||
import 'package:friendica_archive_browser/src/screens/error_screen.dart';
|
||||
import 'package:friendica_archive_browser/src/utils/exec_error.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:result_monad/result_monad.dart';
|
||||
|
||||
import '../../screens/loading_status_screen.dart';
|
||||
import '../../screens/standin_status_screen.dart';
|
||||
|
||||
class FacebookVideosScreen extends StatelessWidget {
|
||||
static final _logger = Logger('$FacebookVideosScreen');
|
||||
|
||||
const FacebookVideosScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_logger.fine('Build FacebookVideosScreen');
|
||||
final service = Provider.of<FacebookArchiveDataService>(context);
|
||||
|
||||
return FutureBuilder<Result<List<FacebookPost>, ExecError>>(
|
||||
future: service.getPosts(),
|
||||
builder: (context, snapshot) {
|
||||
_logger.fine('FacebookVideosScreen Future builder called');
|
||||
|
||||
if (!snapshot.hasData ||
|
||||
snapshot.connectionState != ConnectionState.done) {
|
||||
return const LoadingStatusScreen(title: 'Loading videos');
|
||||
}
|
||||
|
||||
final result = snapshot.requireData;
|
||||
if (result.isFailure) {
|
||||
return ErrorScreen(
|
||||
title: 'Error getting video posts', error: result.error);
|
||||
}
|
||||
|
||||
final videos = result.value
|
||||
.where((p) => p.mediaAttachments
|
||||
.where((m) =>
|
||||
m.estimatedType() == FacebookAttachmentMediaType.video)
|
||||
.isNotEmpty)
|
||||
.toList();
|
||||
|
||||
if (videos.isEmpty) {
|
||||
return const StandInStatusScreen(title: 'No videos were found');
|
||||
}
|
||||
|
||||
_logger.fine('Build Videos ListView');
|
||||
return _FacebookVideosScreenWidget(posts: videos);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class _FacebookVideosScreenWidget extends StatelessWidget {
|
||||
static final _logger = Logger('$_FacebookVideosScreenWidget');
|
||||
final List<FacebookPost> posts;
|
||||
|
||||
const _FacebookVideosScreenWidget({Key? key, required this.posts})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_logger.fine('Redrawing');
|
||||
return FilterControl<FacebookPost, dynamic>(
|
||||
allItems: posts,
|
||||
textSearchFilterFunction: (post, text) =>
|
||||
post.title.contains(text) || post.post.contains(text),
|
||||
itemToDateTimeFunction: (post) =>
|
||||
DateTime.fromMillisecondsSinceEpoch(post.creationTimestamp * 1000),
|
||||
dateRangeFilterFunction: (post, start, stop) =>
|
||||
timestampInRange(post.creationTimestamp * 1000, start, stop),
|
||||
builder: (context, items) {
|
||||
if (items.isEmpty) {
|
||||
return const StandInStatusScreen(
|
||||
title: 'No videos meet filter criteria');
|
||||
}
|
||||
|
||||
return ScrollConfiguration(
|
||||
behavior:
|
||||
ScrollConfiguration.of(context).copyWith(scrollbars: false),
|
||||
child: ListView.separated(
|
||||
primary: false,
|
||||
restorationId: 'facebookVideosListView',
|
||||
itemCount: items.length,
|
||||
itemBuilder: (context, index) {
|
||||
_logger.finer('Rendering Facebook Video List Item');
|
||||
return PostCard(post: items[index]);
|
||||
},
|
||||
separatorBuilder: (context, index) {
|
||||
return const Divider(
|
||||
color: Colors.black,
|
||||
thickness: 0.2,
|
||||
);
|
||||
}),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_friend.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/friendica_contact.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/services/facebook_archive_service.dart';
|
||||
import 'package:friendica_archive_browser/src/screens/error_screen.dart';
|
||||
import 'package:friendica_archive_browser/src/screens/loading_status_screen.dart';
|
||||
|
@ -11,10 +11,10 @@ import 'package:logging/logging.dart';
|
|||
import 'package:provider/provider.dart';
|
||||
import 'package:result_monad/result_monad.dart';
|
||||
|
||||
class FacebookFriendsScreen extends StatelessWidget {
|
||||
static final _logger = Logger('$FacebookFriendsScreen');
|
||||
class FriendsScreen extends StatelessWidget {
|
||||
static final _logger = Logger('$FriendsScreen');
|
||||
|
||||
const FacebookFriendsScreen({Key? key}) : super(key: key);
|
||||
const FriendsScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -22,7 +22,7 @@ class FacebookFriendsScreen extends StatelessWidget {
|
|||
final rootPath = Provider.of<SettingsController>(context).rootFolder;
|
||||
_logger.fine('Build FacebookFriendsScreen');
|
||||
|
||||
return FutureBuilder<Result<List<FacebookFriend>, ExecError>>(
|
||||
return FutureBuilder<Result<List<FriendicaContact>, ExecError>>(
|
||||
future: service.getFriends(),
|
||||
builder: (context, snapshot) {
|
||||
_logger.fine('Future Friends builder called');
|
||||
|
@ -50,7 +50,7 @@ class FacebookFriendsScreen extends StatelessWidget {
|
|||
}
|
||||
|
||||
class _FacebookFriendsScreenWidget extends StatelessWidget {
|
||||
final List<FacebookFriend> friends;
|
||||
final List<FriendicaContact> friends;
|
||||
final String rootPath;
|
||||
|
||||
const _FacebookFriendsScreenWidget(
|
|
@ -6,7 +6,7 @@ import 'package:friendica_archive_browser/src/friendica/components/geo/geo_exten
|
|||
import 'package:friendica_archive_browser/src/friendica/components/geo/map_bounds.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/components/geo/marker_data.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/components/post_card.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_post.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/friendica_post.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/model_utils.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/services/facebook_archive_service.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/services/path_mapping_service.dart';
|
||||
|
@ -25,10 +25,10 @@ import 'package:network_to_file_image/network_to_file_image.dart';
|
|||
import 'package:provider/provider.dart';
|
||||
import 'package:result_monad/result_monad.dart';
|
||||
|
||||
class FacebookGeospatialViewScreen extends StatelessWidget {
|
||||
static final _logger = Logger('$FacebookGeospatialViewScreen');
|
||||
class GeospatialViewScreen extends StatelessWidget {
|
||||
static final _logger = Logger('$GeospatialViewScreen');
|
||||
|
||||
const FacebookGeospatialViewScreen({Key? key}) : super(key: key);
|
||||
const GeospatialViewScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -36,7 +36,7 @@ class FacebookGeospatialViewScreen extends StatelessWidget {
|
|||
final service = Provider.of<FacebookArchiveDataService>(context);
|
||||
final username = Provider.of<SettingsController>(context).facebookName;
|
||||
|
||||
return FutureBuilder<Result<List<FacebookPost>, ExecError>>(
|
||||
return FutureBuilder<Result<List<FriendicaPost>, ExecError>>(
|
||||
future: service.getPosts(),
|
||||
builder: (context, snapshot) {
|
||||
_logger.info('FacebookGeospatialViewScreen Future builder called');
|
||||
|
@ -86,7 +86,7 @@ class FacebookGeospatialViewScreen extends StatelessWidget {
|
|||
}
|
||||
|
||||
class GeospatialView extends StatefulWidget {
|
||||
final List<FacebookPost> posts;
|
||||
final List<FriendicaPost> posts;
|
||||
|
||||
const GeospatialView({Key? key, required this.posts}) : super(key: key);
|
||||
|
||||
|
@ -108,8 +108,8 @@ class _GeospatialViewState extends State<GeospatialView> {
|
|||
);
|
||||
|
||||
Offset? dragStart;
|
||||
final postsInList = <FacebookPost>[];
|
||||
final postsInView = <FacebookPost>[];
|
||||
final postsInList = <FriendicaPost>[];
|
||||
final postsInView = <FriendicaPost>[];
|
||||
double scaleStart = 1.0;
|
||||
|
||||
@override
|
|
@ -3,33 +3,31 @@ import 'dart:io';
|
|||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/components/facebook_media_wrapper_component.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_media_attachment.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/components/media_wrapper_component.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/friendica_media_attachment.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/services/path_mapping_service.dart';
|
||||
import 'package:friendica_archive_browser/src/settings/settings_controller.dart';
|
||||
import 'package:friendica_archive_browser/src/themes.dart';
|
||||
import 'package:friendica_archive_browser/src/utils/snackbar_status_builder.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class FacebookMediaSlideshowScreen extends StatefulWidget {
|
||||
class MediaSlideShowScreen extends StatefulWidget {
|
||||
static const _spacing = 5.0;
|
||||
|
||||
final List<FacebookMediaAttachment> mediaAttachments;
|
||||
final List<FriendicaMediaAttachment> mediaAttachments;
|
||||
final int initialIndex;
|
||||
|
||||
const FacebookMediaSlideshowScreen(
|
||||
const MediaSlideShowScreen(
|
||||
{Key? key, required this.mediaAttachments, required this.initialIndex})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
State<FacebookMediaSlideshowScreen> createState() =>
|
||||
_FacebookMediaSlideshowScreenState();
|
||||
State<MediaSlideShowScreen> createState() => _MediaSlideShowScreenState();
|
||||
}
|
||||
|
||||
class _FacebookMediaSlideshowScreenState
|
||||
extends State<FacebookMediaSlideshowScreen> {
|
||||
class _MediaSlideShowScreenState extends State<MediaSlideShowScreen> {
|
||||
static const fastestChangeMS = 250;
|
||||
FacebookMediaAttachment media = FacebookMediaAttachment.blank();
|
||||
FriendicaMediaAttachment media = FriendicaMediaAttachment.blank();
|
||||
int index = 0;
|
||||
int lastKeyInducedIndexChange = 0;
|
||||
|
||||
|
@ -113,15 +111,13 @@ class _FacebookMediaSlideshowScreenState
|
|||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: FacebookMediaWrapperComponent(
|
||||
child: MediaWrapperComponent(
|
||||
mediaAttachment: media,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: FacebookMediaSlideshowScreen._spacing),
|
||||
const SizedBox(height: MediaSlideShowScreen._spacing),
|
||||
SelectableText(media.description),
|
||||
const SizedBox(
|
||||
height: FacebookMediaSlideshowScreen._spacing),
|
||||
const SizedBox(height: MediaSlideShowScreen._spacing),
|
||||
SelectableText(
|
||||
formatter.format(DateTime.fromMillisecondsSinceEpoch(
|
||||
media.creationTimestamp * 1000)),
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/components/facebook_media_wrapper_component.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/components/filter_control_component.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_album.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/components/media_wrapper_component.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/friendica_album.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/model_utils.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/services/facebook_archive_service.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/services/path_mapping_service.dart';
|
||||
|
@ -14,19 +14,19 @@ import 'package:result_monad/result_monad.dart';
|
|||
|
||||
import '../../screens/loading_status_screen.dart';
|
||||
import '../../screens/standin_status_screen.dart';
|
||||
import 'facebook_photo_album_screen.dart';
|
||||
import 'photo_album_screen.dart';
|
||||
|
||||
class FacebookPhotoAlbumsBrowserScreen extends StatelessWidget {
|
||||
static final _logger = Logger('$FacebookPhotoAlbumsBrowserScreen');
|
||||
class PhotoAlbumsBrowserScreen extends StatelessWidget {
|
||||
static final _logger = Logger('$PhotoAlbumsBrowserScreen');
|
||||
|
||||
const FacebookPhotoAlbumsBrowserScreen({Key? key}) : super(key: key);
|
||||
const PhotoAlbumsBrowserScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_logger.fine('Build FacebookAlbumListView');
|
||||
final service = Provider.of<FacebookArchiveDataService>(context);
|
||||
|
||||
return FutureBuilder<Result<List<FacebookAlbum>, ExecError>>(
|
||||
return FutureBuilder<Result<List<FriendicaAlbum>, ExecError>>(
|
||||
future: service.getAlbums(),
|
||||
builder: (futureBuilderContext, snapshot) {
|
||||
_logger.fine('FacebookAlbumListView Future builder called');
|
||||
|
@ -55,7 +55,7 @@ class FacebookPhotoAlbumsBrowserScreen extends StatelessWidget {
|
|||
}
|
||||
|
||||
class _FacebookPhotoAlbumsBrowserScreenWidget extends StatelessWidget {
|
||||
final List<FacebookAlbum> albums;
|
||||
final List<FriendicaAlbum> albums;
|
||||
|
||||
const _FacebookPhotoAlbumsBrowserScreenWidget(
|
||||
{Key? key, required this.albums})
|
||||
|
@ -66,7 +66,7 @@ class _FacebookPhotoAlbumsBrowserScreenWidget extends StatelessWidget {
|
|||
final settingsController = Provider.of<SettingsController>(context);
|
||||
final pathMapper = Provider.of<PathMappingService>(context);
|
||||
|
||||
return FilterControl<FacebookAlbum, dynamic>(
|
||||
return FilterControl<FriendicaAlbum, dynamic>(
|
||||
allItems: albums,
|
||||
textSearchFilterFunction: (album, text) =>
|
||||
album.name.contains(text) || album.description.contains(text),
|
||||
|
@ -96,7 +96,7 @@ class _FacebookPhotoAlbumsBrowserScreenWidget extends StatelessWidget {
|
|||
return MultiProvider(providers: [
|
||||
ChangeNotifierProvider.value(value: settingsController),
|
||||
Provider.value(value: pathMapper)
|
||||
], child: FacebookPhotoAlbumScreen(album: album));
|
||||
], child: PhotoAlbumScreen(album: album));
|
||||
}));
|
||||
},
|
||||
child: SizedBox(
|
||||
|
@ -106,7 +106,7 @@ class _FacebookPhotoAlbumsBrowserScreenWidget extends StatelessWidget {
|
|||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
FacebookMediaWrapperComponent(
|
||||
MediaWrapperComponent(
|
||||
preferredWidth: 150,
|
||||
preferredHeight: 150,
|
||||
mediaAttachment: album.coverPhoto),
|
|
@ -1,8 +1,8 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/components/facebook_media_wrapper_component.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/components/filter_control_component.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_album.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_media_attachment.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/components/media_wrapper_component.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/friendica_album.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/friendica_media_attachment.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/model_utils.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/services/path_mapping_service.dart';
|
||||
import 'package:friendica_archive_browser/src/screens/standin_status_screen.dart';
|
||||
|
@ -10,14 +10,13 @@ import 'package:friendica_archive_browser/src/settings/settings_controller.dart'
|
|||
import 'package:logging/logging.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'facebook_media_slideshow_screen.dart';
|
||||
import 'media_slideshow_screen.dart';
|
||||
|
||||
class FacebookPhotoAlbumScreen extends StatelessWidget {
|
||||
static final _logger = Logger('$FacebookPhotoAlbumScreen');
|
||||
final FacebookAlbum album;
|
||||
class PhotoAlbumScreen extends StatelessWidget {
|
||||
static final _logger = Logger('$PhotoAlbumScreen');
|
||||
final FriendicaAlbum album;
|
||||
|
||||
const FacebookPhotoAlbumScreen({Key? key, required this.album})
|
||||
: super(key: key);
|
||||
const PhotoAlbumScreen({Key? key, required this.album}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -26,7 +25,7 @@ class FacebookPhotoAlbumScreen extends StatelessWidget {
|
|||
|
||||
return album.photos.isEmpty
|
||||
? _buildEmptyGalleryScrene(context)
|
||||
: FilterControl<FacebookMediaAttachment, dynamic>(
|
||||
: FilterControl<FriendicaMediaAttachment, dynamic>(
|
||||
allItems: album.photos,
|
||||
textSearchFilterFunction: (photo, text) =>
|
||||
photo.title.contains(text) || photo.description.contains(text),
|
||||
|
@ -57,7 +56,7 @@ class FacebookPhotoAlbumScreen extends StatelessWidget {
|
|||
|
||||
class _FacebookPhotoAlbumScreenWidget extends StatelessWidget {
|
||||
static final _logger = Logger('$_FacebookPhotoAlbumScreenWidget');
|
||||
final List<FacebookMediaAttachment> photos;
|
||||
final List<FriendicaMediaAttachment> photos;
|
||||
final String albumName;
|
||||
final String albumDescription;
|
||||
|
||||
|
@ -116,12 +115,12 @@ class _FacebookPhotoAlbumScreenWidget extends StatelessWidget {
|
|||
value: settingsController),
|
||||
Provider.value(value: pathMapper)
|
||||
],
|
||||
child: FacebookMediaSlideshowScreen(
|
||||
child: MediaSlideShowScreen(
|
||||
mediaAttachments: photos,
|
||||
initialIndex: index));
|
||||
}));
|
||||
},
|
||||
child: FacebookMediaWrapperComponent(
|
||||
child: MediaWrapperComponent(
|
||||
mediaAttachment: photos[index],
|
||||
preferredWidth: 300,
|
||||
preferredHeight: 300,
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/components/filter_control_component.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/components/post_card.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_post.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/friendica_post.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/model_utils.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/services/facebook_archive_service.dart';
|
||||
import 'package:friendica_archive_browser/src/screens/error_screen.dart';
|
||||
|
@ -14,10 +14,10 @@ import 'package:result_monad/result_monad.dart';
|
|||
import '../../screens/loading_status_screen.dart';
|
||||
import '../../screens/standin_status_screen.dart';
|
||||
|
||||
class FacebookPostsScreen extends StatelessWidget {
|
||||
static final _logger = Logger('$FacebookPostsScreen');
|
||||
class PostsScreen extends StatelessWidget {
|
||||
static final _logger = Logger('$PostsScreen');
|
||||
|
||||
const FacebookPostsScreen({Key? key}) : super(key: key);
|
||||
const PostsScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -25,7 +25,7 @@ class FacebookPostsScreen extends StatelessWidget {
|
|||
final service = Provider.of<FacebookArchiveDataService>(context);
|
||||
final username = Provider.of<SettingsController>(context).facebookName;
|
||||
|
||||
return FutureBuilder<Result<List<FacebookPost>, ExecError>>(
|
||||
return FutureBuilder<Result<List<FriendicaPost>, ExecError>>(
|
||||
future: service.getPosts(),
|
||||
builder: (context, snapshot) {
|
||||
_logger.info('FacebookPostListView Future builder called');
|
||||
|
@ -82,7 +82,7 @@ class FacebookPostsScreen extends StatelessWidget {
|
|||
class _FacebookPostsScreenWidget extends StatelessWidget {
|
||||
static final _logger = Logger('$_FacebookPostsScreenWidget');
|
||||
|
||||
final List<FacebookPost> posts;
|
||||
final List<FriendicaPost> posts;
|
||||
|
||||
const _FacebookPostsScreenWidget({Key? key, required this.posts})
|
||||
: super(key: key);
|
||||
|
@ -90,7 +90,7 @@ class _FacebookPostsScreenWidget extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_logger.fine('Redrawing');
|
||||
return FilterControl<FacebookPost, dynamic>(
|
||||
return FilterControl<FriendicaPost, dynamic>(
|
||||
allItems: posts,
|
||||
imagesOnlyFilterFunction: (post) => post.hasImages(),
|
||||
videosOnlyFilterFunction: (post) => post.hasVideos(),
|
|
@ -3,7 +3,7 @@ import 'package:friendica_archive_browser/src/components/heatmap_widget.dart';
|
|||
import 'package:friendica_archive_browser/src/components/timechart_widget.dart';
|
||||
import 'package:friendica_archive_browser/src/components/word_frequency_widget.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/components/filter_control_component.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_media_attachment.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/friendica_media_attachment.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/model_utils.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/services/facebook_archive_service.dart';
|
||||
import 'package:friendica_archive_browser/src/models/time_element.dart';
|
||||
|
@ -12,15 +12,15 @@ import 'package:friendica_archive_browser/src/utils/snackbar_status_builder.dart
|
|||
import 'package:logging/logging.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class FacebookStatsScreen extends StatefulWidget {
|
||||
const FacebookStatsScreen({Key? key}) : super(key: key);
|
||||
class StatsScreen extends StatefulWidget {
|
||||
const StatsScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<FacebookStatsScreen> createState() => _FacebookStatsScreenState();
|
||||
State<StatsScreen> createState() => _StatsScreenState();
|
||||
}
|
||||
|
||||
class _FacebookStatsScreenState extends State<FacebookStatsScreen> {
|
||||
static final _logger = Logger("$_FacebookStatsScreenState");
|
||||
class _StatsScreenState extends State<StatsScreen> {
|
||||
static final _logger = Logger("$_StatsScreenState");
|
||||
FacebookArchiveDataService? archiveDataService;
|
||||
final allItems = <TimeElement>[];
|
||||
StatType statType = StatType.selectType;
|
||||
|
@ -90,7 +90,7 @@ class _FacebookStatsScreenState extends State<FacebookStatsScreen> {
|
|||
onSuccess: (posts) => posts
|
||||
.where((post) => post.hasVideos())
|
||||
.expand((post) => post.mediaAttachments.where((m) =>
|
||||
m.estimatedType() == FacebookAttachmentMediaType.video))
|
||||
m.estimatedType() == FriendicaAttachmentMediaType.video))
|
||||
.map((e) => TimeElement(
|
||||
timeInMS: e.creationTimestamp * 1000,
|
||||
hasImages: false,
|
|
@ -2,12 +2,11 @@ import 'dart:convert';
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_album.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_comment.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_friend.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_post.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_saved_item.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_timeline_type.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/friendica_album.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/friendica_comment.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/friendica_contact.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/friendica_post.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/timeline_type.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/services/facebook_file_reader.dart';
|
||||
import 'package:friendica_archive_browser/src/utils/exec_error.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
@ -41,15 +40,14 @@ class FacebookArchiveFolderReader extends ChangeNotifier {
|
|||
_logger.fine('Create new FacebookArchiveFolderReader');
|
||||
}
|
||||
|
||||
FutureResult<List<FacebookPost>, ExecError> readPosts() async {
|
||||
final posts = <FacebookPost>[];
|
||||
FutureResult<List<FriendicaPost>, ExecError> readPosts() async {
|
||||
final posts = <FriendicaPost>[];
|
||||
final errors = <ExecError>[];
|
||||
|
||||
final yourPostPath = '$rootDirectoryPath/posts/your_posts_1.json';
|
||||
if (File(yourPostPath).existsSync()) {
|
||||
(await _getJsonList(yourPostPath))
|
||||
.andThen(
|
||||
(json) => _parsePostResults(json, FacebookTimelineType.active))
|
||||
.andThen((json) => _parsePostResults(json, TimelineType.active))
|
||||
.match(
|
||||
onSuccess: (newPosts) => posts.addAll(newPosts),
|
||||
onError: (error) {
|
||||
|
@ -66,8 +64,8 @@ class FacebookArchiveFolderReader extends ChangeNotifier {
|
|||
? Result.ok(json['archive_v2'])
|
||||
: Result.error(
|
||||
ExecError.message('No archive_v2 key in $archivedPostsPath')))
|
||||
.andThen((archivedPostsJson) => _parsePostResults(
|
||||
archivedPostsJson, FacebookTimelineType.archive))
|
||||
.andThen((archivedPostsJson) =>
|
||||
_parsePostResults(archivedPostsJson, TimelineType.archive))
|
||||
.match(
|
||||
onSuccess: (archivedPosts) => posts.addAll(archivedPosts),
|
||||
onError: (error) {
|
||||
|
@ -85,7 +83,7 @@ class FacebookArchiveFolderReader extends ChangeNotifier {
|
|||
: Result.error(
|
||||
ExecError.message('No trash_v2 key in $trashPostsPath')))
|
||||
.andThen((archivedPostsJson) =>
|
||||
_parsePostResults(archivedPostsJson, FacebookTimelineType.trash))
|
||||
_parsePostResults(archivedPostsJson, TimelineType.trash))
|
||||
.match(
|
||||
onSuccess: (archivedPosts) => posts.addAll(archivedPosts),
|
||||
onError: (error) {
|
||||
|
@ -103,7 +101,7 @@ class FacebookArchiveFolderReader extends ChangeNotifier {
|
|||
return Result.ok(posts);
|
||||
}
|
||||
|
||||
FutureResult<List<FacebookComment>, ExecError> readComments() async {
|
||||
FutureResult<List<FriendicaComment>, ExecError> readComments() async {
|
||||
final path = '$rootDirectoryPath/comments_and_reactions/comments.json';
|
||||
final jsonResult = await _getJson(path);
|
||||
if (jsonResult.isFailure) {
|
||||
|
@ -117,8 +115,9 @@ class FacebookArchiveFolderReader extends ChangeNotifier {
|
|||
}
|
||||
|
||||
final commentsJson = jsonData['comments_v2'] as List<dynamic>;
|
||||
final commentsResult = runCatching(() => Result.ok(
|
||||
commentsJson.map((e) => FacebookComment.fromFacebookJson(e)).toList()));
|
||||
final commentsResult = runCatching(() => Result.ok(commentsJson
|
||||
.map((e) => FriendicaComment.fromFacebookJson(e))
|
||||
.toList()));
|
||||
|
||||
commentsResult.match(
|
||||
onSuccess: (value) => _logger.fine('Comments processed into PODOs'),
|
||||
|
@ -128,10 +127,10 @@ class FacebookArchiveFolderReader extends ChangeNotifier {
|
|||
return commentsResult.mapExceptionErrorToExecError();
|
||||
}
|
||||
|
||||
FutureResult<List<FacebookAlbum>, ExecError> readPhotoAlbums() async {
|
||||
FutureResult<List<FriendicaAlbum>, ExecError> readPhotoAlbums() async {
|
||||
final albumFolderPath = '$rootDirectoryPath/posts/album';
|
||||
final folder = Directory(albumFolderPath);
|
||||
final albums = <FacebookAlbum>[];
|
||||
final albums = <FriendicaAlbum>[];
|
||||
|
||||
if (!folder.existsSync()) {
|
||||
final msg = 'Photos folder does not exist; $albumFolderPath';
|
||||
|
@ -157,7 +156,7 @@ class FacebookArchiveFolderReader extends ChangeNotifier {
|
|||
jsonResult.match(
|
||||
onSuccess: (json) {
|
||||
final albumResult =
|
||||
runCatching(() => Result.ok(FacebookAlbum.fromJson(json)));
|
||||
runCatching(() => Result.ok(FriendicaAlbum.fromJson(json)));
|
||||
albumResult.match(
|
||||
onSuccess: (album) {
|
||||
albums.add(album);
|
||||
|
@ -173,14 +172,14 @@ class FacebookArchiveFolderReader extends ChangeNotifier {
|
|||
return Result.ok(albums);
|
||||
}
|
||||
|
||||
FutureResult<List<FacebookFriend>, ExecError> readFriends() async {
|
||||
FutureResult<List<FriendicaContact>, ExecError> readFriends() async {
|
||||
final basePath = '$rootDirectoryPath/friends_and_followers';
|
||||
final friendsFile = File('$basePath/friends.json');
|
||||
final receivedFile = File('$basePath/friend_requests_received.json');
|
||||
final rejectedFile = File('$basePath/rejected_friend_requests.json');
|
||||
final removedFile = File('$basePath/removed_friends.json');
|
||||
final sentFile = File('$basePath/friend_requests_sent.json');
|
||||
final allFriends = <FacebookFriend>[];
|
||||
final allFriends = <FriendicaContact>[];
|
||||
|
||||
if (!Directory(basePath).existsSync()) {
|
||||
_logger.severe('Friends base folder does not exist: $basePath');
|
||||
|
@ -226,39 +225,6 @@ class FacebookArchiveFolderReader extends ChangeNotifier {
|
|||
return Result.ok(allFriends);
|
||||
}
|
||||
|
||||
FutureResult<List<FacebookSavedItem>, ExecError> readSavedItems() async {
|
||||
final path =
|
||||
'$rootDirectoryPath/saved_items_and_collections/saved_items_and_collections.json';
|
||||
final jsonResult = await _getJson(path);
|
||||
if (jsonResult.isFailure) {
|
||||
return Result.error(jsonResult.error);
|
||||
}
|
||||
|
||||
final jsonData = jsonResult.value;
|
||||
if (!jsonData.containsKey('saves_and_collections_v2')) {
|
||||
return Result.error(ExecError(
|
||||
errorMessage:
|
||||
'Saved Items and Collections JSON file is malformed: $path'));
|
||||
}
|
||||
|
||||
final savedItemsJson =
|
||||
jsonData['saves_and_collections_v2'] as List<dynamic>;
|
||||
final savedItemsResult = runCatching(() => Result.ok(savedItemsJson
|
||||
.map((e) => FacebookSavedItem.fromFacebookJson(e))
|
||||
.toList()));
|
||||
|
||||
savedItemsResult
|
||||
.andThen(
|
||||
(items) => Result.ok(items.where((e) => e.timestamp != 0).toList()))
|
||||
.match(
|
||||
onSuccess: (value) =>
|
||||
_logger.fine('Saved Items processed into PODOs'),
|
||||
onError: (error) => _logger
|
||||
.severe('Error mapping JSON to saved items data: $error'));
|
||||
|
||||
return savedItemsResult.mapExceptionErrorToExecError();
|
||||
}
|
||||
|
||||
static bool validateCanReadArchive(String path) {
|
||||
_logger.fine('Validating whether path is a valid Facebook Archive: $path');
|
||||
final baseDir = Directory(path);
|
||||
|
@ -277,10 +243,10 @@ class FacebookArchiveFolderReader extends ChangeNotifier {
|
|||
return true;
|
||||
}
|
||||
|
||||
Result<List<FacebookPost>, ExecError> _parsePostResults(
|
||||
List<dynamic> json, FacebookTimelineType timelineType) {
|
||||
Result<List<FriendicaPost>, ExecError> _parsePostResults(
|
||||
List<dynamic> json, TimelineType timelineType) {
|
||||
final postsResult = runCatching(() => Result.ok(
|
||||
json.map((e) => FacebookPost.fromJson(e, timelineType)).toList()));
|
||||
json.map((e) => FriendicaPost.fromJson(e, timelineType)).toList()));
|
||||
|
||||
postsResult.match(
|
||||
onSuccess: (value) => _logger.fine('Posts processed into PODOs'),
|
||||
|
@ -351,9 +317,9 @@ class FacebookArchiveFolderReader extends ChangeNotifier {
|
|||
return jsonParseResult;
|
||||
}
|
||||
|
||||
FutureResult<List<FacebookFriend>, ExecError> _readFriendsJsonFile(
|
||||
FutureResult<List<FriendicaContact>, ExecError> _readFriendsJsonFile(
|
||||
File file, FriendStatus status, String topKey) async {
|
||||
final friends = <FacebookFriend>[];
|
||||
final friends = <FriendicaContact>[];
|
||||
|
||||
if (file.existsSync()) {
|
||||
final json = (await _getJson(file.path)).fold(
|
||||
|
@ -364,7 +330,8 @@ class FacebookArchiveFolderReader extends ChangeNotifier {
|
|||
});
|
||||
final List<dynamic> invited = json[topKey] ?? <Map<String, dynamic>>[];
|
||||
try {
|
||||
final entries = invited.map((f) => FacebookFriend.fromJson(f, status));
|
||||
final entries =
|
||||
invited.map((f) => FriendicaContact.fromJson(f, status));
|
||||
_logger.fine(
|
||||
'${entries.length} friends of type $status found in ${file.path}');
|
||||
friends.addAll(entries);
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_album.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_comment.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_friend.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_media_attachment.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_post.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/facebook_saved_item.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/friendica_album.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/friendica_comment.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/friendica_contact.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/friendica_media_attachment.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/models/friendica_post.dart';
|
||||
import 'package:friendica_archive_browser/src/friendica/services/path_mapping_service.dart';
|
||||
import 'package:friendica_archive_browser/src/utils/exec_error.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:result_monad/result_monad.dart';
|
||||
|
||||
import 'facebook_archive_reader.dart';
|
||||
|
@ -19,11 +17,10 @@ class FacebookArchiveDataService extends ChangeNotifier {
|
|||
static final _logger = Logger('$FacebookArchiveDataService');
|
||||
final PathMappingService pathMappingService;
|
||||
final String appDataDirectory;
|
||||
final List<FacebookAlbum> albums = [];
|
||||
final List<FacebookPost> posts = [];
|
||||
final List<FacebookComment> comments = [];
|
||||
final List<FacebookFriend> friends = [];
|
||||
final List<FacebookSavedItem> savedItems = [];
|
||||
final List<FriendicaAlbum> albums = [];
|
||||
final List<FriendicaPost> posts = [];
|
||||
final List<FriendicaComment> comments = [];
|
||||
final List<FriendicaContact> friends = [];
|
||||
bool canUseConvoCacheFile = true;
|
||||
|
||||
FacebookArchiveDataService(
|
||||
|
@ -38,29 +35,12 @@ class FacebookArchiveDataService extends ChangeNotifier {
|
|||
posts.clear();
|
||||
comments.clear();
|
||||
friends.clear();
|
||||
savedItems.clear();
|
||||
notifyListeners();
|
||||
canUseConvoCacheFile = false;
|
||||
_logger.finer('Deleting files');
|
||||
try {
|
||||
final convoCacheFile = File(_conversationCachePath);
|
||||
if (convoCacheFile.existsSync()) {
|
||||
convoCacheFile.deleteSync();
|
||||
}
|
||||
|
||||
if (convoCacheFile.existsSync()) {
|
||||
_logger.severe(
|
||||
'Attempted to delete conversations cache file but it did not succeed. ${convoCacheFile.path}');
|
||||
}
|
||||
} catch (e) {
|
||||
_logger.severe(
|
||||
'Exception thrown while attempting to clear conversations cache file: $e');
|
||||
}
|
||||
canUseConvoCacheFile = true;
|
||||
_logger.fine('clearCaches complete');
|
||||
}
|
||||
|
||||
FutureResult<List<FacebookPost>, ExecError> getPosts() async {
|
||||
FutureResult<List<FriendicaPost>, ExecError> getPosts() async {
|
||||
_logger.fine('Request for posts');
|
||||
if (posts.isNotEmpty) {
|
||||
_logger.fine(
|
||||
|
@ -82,7 +62,7 @@ class FacebookArchiveDataService extends ChangeNotifier {
|
|||
return Result.ok(List.unmodifiable(posts));
|
||||
}
|
||||
|
||||
FutureResult<List<FacebookComment>, ExecError> getComments() async {
|
||||
FutureResult<List<FriendicaComment>, ExecError> getComments() async {
|
||||
_logger.fine('Request for comments');
|
||||
if (comments.isNotEmpty) {
|
||||
_logger.fine(
|
||||
|
@ -104,7 +84,7 @@ class FacebookArchiveDataService extends ChangeNotifier {
|
|||
return Result.ok(List.unmodifiable(comments));
|
||||
}
|
||||
|
||||
FutureResult<List<FacebookFriend>, ExecError> getFriends() async {
|
||||
FutureResult<List<FriendicaContact>, ExecError> getFriends() async {
|
||||
_logger.fine('Request for friends');
|
||||
if (friends.isNotEmpty) {
|
||||
_logger.fine(
|
||||
|
@ -124,7 +104,7 @@ class FacebookArchiveDataService extends ChangeNotifier {
|
|||
return Result.ok(List.unmodifiable(friends));
|
||||
}
|
||||
|
||||
FutureResult<List<FacebookAlbum>, ExecError> getAlbums() async {
|
||||
FutureResult<List<FriendicaAlbum>, ExecError> getAlbums() async {
|
||||
_logger.fine('Request for albums');
|
||||
if (albums.isNotEmpty) {
|
||||
_logger.fine(
|
||||
|
@ -154,32 +134,8 @@ class FacebookArchiveDataService extends ChangeNotifier {
|
|||
return Result.ok(List.unmodifiable(albums));
|
||||
}
|
||||
|
||||
FutureResult<List<FacebookSavedItem>, ExecError> getSavedItems() async {
|
||||
_logger.fine('Request for saved items');
|
||||
if (savedItems.isNotEmpty) {
|
||||
_logger.fine(
|
||||
'Saved items already loaded, returning existing ${savedItems.length} comments');
|
||||
return Result.ok(List.unmodifiable(savedItems));
|
||||
}
|
||||
_logger.finer('No previously pulled saved items, reading from disk');
|
||||
final savedItemsResult = await _readAllSavedItems();
|
||||
savedItemsResult.match(
|
||||
onSuccess: (newSavedItems) {
|
||||
savedItems.clear();
|
||||
savedItems.addAll(newSavedItems);
|
||||
savedItems.sort((c1, c2) => -c1.timestamp.compareTo(c2.timestamp));
|
||||
},
|
||||
onError: (error) => _logger.severe('Error loading savedItems: $error'));
|
||||
|
||||
_logger.fine('Returning ${savedItems.length} saved items');
|
||||
return Result.ok(List.unmodifiable(savedItems));
|
||||
}
|
||||
|
||||
String get _conversationCachePath =>
|
||||
p.join(appDataDirectory, 'convo_cache.json');
|
||||
|
||||
FutureResult<List<FacebookPost>, ExecError> _readAllPosts() async {
|
||||
final allPosts = <FacebookPost>[];
|
||||
FutureResult<List<FriendicaPost>, ExecError> _readAllPosts() async {
|
||||
final allPosts = <FriendicaPost>[];
|
||||
bool hadSuccess = false;
|
||||
for (final topLevelDir in _topLevelDirs) {
|
||||
try {
|
||||
|
@ -206,8 +162,8 @@ class FacebookArchiveDataService extends ChangeNotifier {
|
|||
'Unable to find any post JSON files in $_baseArchiveFolder'));
|
||||
}
|
||||
|
||||
FutureResult<List<FacebookComment>, ExecError> _readAllComments() async {
|
||||
final allComments = <FacebookComment>[];
|
||||
FutureResult<List<FriendicaComment>, ExecError> _readAllComments() async {
|
||||
final allComments = <FriendicaComment>[];
|
||||
bool hadSuccess = false;
|
||||
for (final topLevelDir in _topLevelDirs) {
|
||||
try {
|
||||
|
@ -234,8 +190,8 @@ class FacebookArchiveDataService extends ChangeNotifier {
|
|||
'Unable to find any comment JSON files in $_baseArchiveFolder'));
|
||||
}
|
||||
|
||||
FutureResult<List<FacebookFriend>, ExecError> _readAllFriends() async {
|
||||
final allFriends = <FacebookFriend>[];
|
||||
FutureResult<List<FriendicaContact>, ExecError> _readAllFriends() async {
|
||||
final allFriends = <FriendicaContact>[];
|
||||
bool hadSuccess = false;
|
||||
for (final topLevelDir in _topLevelDirs) {
|
||||
try {
|
||||
|
@ -262,8 +218,8 @@ class FacebookArchiveDataService extends ChangeNotifier {
|
|||
'Unable to find any album JSON files in $_baseArchiveFolder'));
|
||||
}
|
||||
|
||||
FutureResult<List<FacebookAlbum>, ExecError> _readAllAlbums() async {
|
||||
final allAlbums = <FacebookAlbum>[];
|
||||
FutureResult<List<FriendicaAlbum>, ExecError> _readAllAlbums() async {
|
||||
final allAlbums = <FriendicaAlbum>[];
|
||||
bool hadSuccess = false;
|
||||
for (final topLevelDir in _topLevelDirs) {
|
||||
try {
|
||||
|
@ -290,35 +246,7 @@ class FacebookArchiveDataService extends ChangeNotifier {
|
|||
'Unable to find any album JSON files in $_baseArchiveFolder'));
|
||||
}
|
||||
|
||||
FutureResult<List<FacebookSavedItem>, ExecError> _readAllSavedItems() async {
|
||||
final allSavedItems = <FacebookSavedItem>[];
|
||||
bool hadSuccess = false;
|
||||
for (final topLevelDir in _topLevelDirs) {
|
||||
try {
|
||||
_logger.fine(
|
||||
'Attempting to find/parse saved items JSON data in ${topLevelDir.path}');
|
||||
final reader = FacebookArchiveFolderReader(topLevelDir.path);
|
||||
final savedItemsResult = await reader.readSavedItems();
|
||||
savedItemsResult.match(
|
||||
onSuccess: (newSavedItem) {
|
||||
allSavedItems.addAll(newSavedItem);
|
||||
hadSuccess = true;
|
||||
},
|
||||
onError: (error) => _logger.fine(error));
|
||||
} catch (e) {
|
||||
_logger.severe('Exception thrown trying to read saved items, $e');
|
||||
}
|
||||
}
|
||||
|
||||
if (hadSuccess) {
|
||||
return Result.ok(allSavedItems);
|
||||
}
|
||||
|
||||
return Result.error(ExecError.message(
|
||||
'Unable to find any saved items JSON files in $_baseArchiveFolder'));
|
||||
}
|
||||
|
||||
FutureResult<FacebookAlbum, ExecError> _generatePostsAlbum() async {
|
||||
FutureResult<FriendicaAlbum, ExecError> _generatePostsAlbum() async {
|
||||
const name = 'Photos in Posts';
|
||||
const description = 'Photos that were added to posts';
|
||||
final posts = await getPosts();
|
||||
|
@ -330,15 +258,15 @@ class FacebookArchiveDataService extends ChangeNotifier {
|
|||
final photos = posts.value
|
||||
.map((p) => p.mediaAttachments)
|
||||
.expand((m) => m)
|
||||
.where((m) => m.estimatedType() == FacebookAttachmentMediaType.image)
|
||||
.where((m) => m.estimatedType() == FriendicaAttachmentMediaType.image)
|
||||
.toList();
|
||||
photos
|
||||
.sort((p1, p2) => p1.creationTimestamp.compareTo(p2.creationTimestamp));
|
||||
final lastModified = photos.isEmpty ? 0 : photos.last.creationTimestamp;
|
||||
final coverPhoto =
|
||||
photos.isEmpty ? FacebookMediaAttachment.blank() : photos.last;
|
||||
photos.isEmpty ? FriendicaMediaAttachment.blank() : photos.last;
|
||||
|
||||
final album = FacebookAlbum(
|
||||
final album = FriendicaAlbum(
|
||||
name: name,
|
||||
description: description,
|
||||
lastModifiedTimestamp: lastModified,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'friendica/screens/facebook_photo_album_browser_screen.dart';
|
||||
import 'friendica/screens/facebook_posts_screen.dart';
|
||||
import 'friendica/screens/facebook_stats_screen.dart';
|
||||
import 'friendica/screens/photo_album_browser_screen.dart';
|
||||
import 'friendica/screens/posts_screen.dart';
|
||||
import 'friendica/screens/stats_screen.dart';
|
||||
import 'friendica/services/facebook_archive_reader.dart';
|
||||
import 'settings/settings_controller.dart';
|
||||
import 'settings/settings_view.dart';
|
||||
|
@ -25,10 +25,10 @@ class _HomeState extends State<Home> {
|
|||
@override
|
||||
void initState() {
|
||||
_pageData.addAll([
|
||||
AppPageData('Posts', Icons.home, () => const FacebookPostsScreen()),
|
||||
AppPageData('Posts', Icons.home, () => const PostsScreen()),
|
||||
AppPageData('Photos', Icons.photo_library,
|
||||
() => const FacebookPhotoAlbumsBrowserScreen()),
|
||||
AppPageData('Stats', Icons.bar_chart, () => const FacebookStatsScreen()),
|
||||
() => const PhotoAlbumsBrowserScreen()),
|
||||
AppPageData('Stats', Icons.bar_chart, () => const StatsScreen()),
|
||||
AppPageData('Settings', Icons.settings, () => _buildSettingsView()),
|
||||
]);
|
||||
for (var i = 0; i < _pageData.length; i++) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"appTitle": "Kyanite",
|
||||
"appTitle": "Friendica Archive Browser",
|
||||
"@appTitle": {
|
||||
"description": "A viewer of Facebook Archive Folders"
|
||||
"description": "A browser of Friendica Archive Folders"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import 'dart:ui';
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class FacebookAppScrollingBehavior extends MaterialScrollBehavior {
|
||||
class AppScrollingBehavior extends MaterialScrollBehavior {
|
||||
@override
|
||||
Set<PointerDeviceKind> get dragDevices => {
|
||||
PointerDeviceKind.touch,
|
||||
|
|
|
@ -49,13 +49,4 @@ void main() {
|
|||
onError: (error) => fail(error.toString()));
|
||||
});
|
||||
});
|
||||
|
||||
group('Test Read Saved Items JSON', () {
|
||||
test('Read savedItems from disk', () async {
|
||||
final savedItems =
|
||||
(await FacebookArchiveFolderReader(rootPath).readSavedItems()).value;
|
||||
expect(savedItems.length, equals(6));
|
||||
savedItems.forEach(print);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -25,9 +25,13 @@ void main() {
|
|||
test('With Data', () {
|
||||
final data = [
|
||||
TimeElement(timeInMS: DateTime(2020, 10, 19).millisecondsSinceEpoch),
|
||||
TimeElement(timeInMS: DateTime(2020, 10, 20, 12,00,00).millisecondsSinceEpoch),
|
||||
TimeElement(timeInMS: DateTime(2020, 10, 20, 13,00,00).millisecondsSinceEpoch),
|
||||
TimeElement(timeInMS: DateTime(2020, 10, 23).millisecondsSinceEpoch),
|
||||
TimeElement(
|
||||
timeInMS:
|
||||
DateTime(2020, 10, 20, 12, 00, 00).millisecondsSinceEpoch),
|
||||
TimeElement(
|
||||
timeInMS:
|
||||
DateTime(2020, 10, 20, 13, 00, 00).millisecondsSinceEpoch),
|
||||
TimeElement(timeInMS: DateTime(2020, 10, 23).millisecondsSinceEpoch),
|
||||
TimeElement(timeInMS: DateTime(2020, 10, 24).millisecondsSinceEpoch),
|
||||
TimeElement(timeInMS: DateTime(2020, 10, 25).millisecondsSinceEpoch),
|
||||
TimeElement(timeInMS: DateTime(2021, 10, 26).millisecondsSinceEpoch),
|
||||
|
@ -39,8 +43,8 @@ void main() {
|
|||
final expected = i == 0
|
||||
? 1
|
||||
: i == 1
|
||||
? 2
|
||||
: 1;
|
||||
? 2
|
||||
: 1;
|
||||
expect(bins[i].count, equals(expected));
|
||||
}
|
||||
});
|
||||
|
@ -80,8 +84,8 @@ void main() {
|
|||
final expected = i == 0
|
||||
? 2
|
||||
: i == 1
|
||||
? 4
|
||||
: 1;
|
||||
? 4
|
||||
: 1;
|
||||
expect(bins[i].count, equals(expected));
|
||||
}
|
||||
});
|
||||
|
@ -121,14 +125,13 @@ void main() {
|
|||
final expected = i == 0
|
||||
? 2
|
||||
: i == 1
|
||||
? 4
|
||||
: 1;
|
||||
? 4
|
||||
: 1;
|
||||
expect(bins[i].count, equals(expected));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
group('Test Yearly stats', () {
|
||||
test('With no data', () {
|
||||
final bins = TimeStatGenerator([]).calculateStatsByYear();
|
||||
|
@ -157,11 +160,10 @@ void main() {
|
|||
final expected = i == 0
|
||||
? 4
|
||||
: i == 1
|
||||
? 3
|
||||
: 2;
|
||||
? 3
|
||||
: 2;
|
||||
expect(bins[i].count, equals(expected));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import 'package:flutter_test/flutter_test.dart';
|
|||
import 'package:friendica_archive_browser/src/utils/word_map_generator.dart';
|
||||
|
||||
void main() {
|
||||
|
||||
test('Empty collection stats', () {
|
||||
final generator = WordMapGenerator();
|
||||
expect(generator.getTopList(10).isEmpty, true);
|
||||
|
@ -16,8 +15,8 @@ void main() {
|
|||
final list = generator.getTopList(10);
|
||||
list.forEach(print);
|
||||
expect(list.length, equals(8));
|
||||
expect(list.firstWhere((e) => e.word=='the').count, equals(2));
|
||||
expect(list.firstWhere((e) => e.word=='dog').count, equals(1));
|
||||
expect(list.firstWhere((e) => e.word == 'the').count, equals(2));
|
||||
expect(list.firstWhere((e) => e.word == 'dog').count, equals(1));
|
||||
});
|
||||
|
||||
test('Test case-insensitive', () {
|
||||
|
@ -26,7 +25,7 @@ void main() {
|
|||
final list = generator.getTopList(10);
|
||||
list.forEach(print);
|
||||
expect(list.length, equals(1));
|
||||
expect(list.firstWhere((e) => e.word=='the').count, equals(5));
|
||||
expect(list.firstWhere((e) => e.word == 'the').count, equals(5));
|
||||
});
|
||||
|
||||
test('Test punctuation filtering', () {
|
||||
|
@ -40,7 +39,7 @@ void main() {
|
|||
final list = generator.getTopList(10);
|
||||
list.forEach(print);
|
||||
expect(list.length, equals(1));
|
||||
expect(list.firstWhere((e) => e.word=='the').count, equals(34));
|
||||
expect(list.firstWhere((e) => e.word == 'the').count, equals(34));
|
||||
});
|
||||
|
||||
test('Test minimum word size filter', () {
|
||||
|
@ -49,6 +48,7 @@ void main() {
|
|||
final list = generator.getTopList(10);
|
||||
list.forEach(print);
|
||||
expect(list.length, equals(2));
|
||||
expect(list.map((e) => e.word).toSet().containsAll(['test', 'testing']), true);
|
||||
expect(
|
||||
list.map((e) => e.word).toSet().containsAll(['test', 'testing']), true);
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue