mirror of
https://gitlab.com/mysocialportal/relatica
synced 2024-10-18 13:33:32 +00:00
Add updatePost to get all comments on post
This commit is contained in:
parent
1524cc217a
commit
37857a96d6
6 changed files with 102 additions and 23 deletions
|
@ -1,6 +1,8 @@
|
||||||
import 'package:cached_network_image/cached_network_image.dart';
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_portal/services/entry_manager_service.dart';
|
||||||
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
|
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
|
||||||
|
import 'package:result_monad/result_monad.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
import '../../globals.dart';
|
import '../../globals.dart';
|
||||||
|
@ -15,12 +17,24 @@ import '../../utils/snackbar_builder.dart';
|
||||||
import '../padding.dart';
|
import '../padding.dart';
|
||||||
import 'interactions_bar_control.dart';
|
import 'interactions_bar_control.dart';
|
||||||
|
|
||||||
class StatusControl extends StatelessWidget {
|
class StatusControl extends StatefulWidget {
|
||||||
final EntryTreeItem item;
|
final EntryTreeItem originalItem;
|
||||||
|
|
||||||
|
const StatusControl({super.key, required this.originalItem});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<StatusControl> createState() => _StatusControlState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _StatusControlState extends State<StatusControl> {
|
||||||
|
late EntryTreeItem item;
|
||||||
TimelineEntry get entry => item.entry;
|
TimelineEntry get entry => item.entry;
|
||||||
|
|
||||||
const StatusControl({super.key, required this.item});
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
item = widget.originalItem;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -166,7 +180,7 @@ class StatusControl extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildChildComments(BuildContext context) {
|
Widget buildChildComments(BuildContext context) {
|
||||||
final comments = item.children;
|
final comments = widget.originalItem.children;
|
||||||
if (comments.isEmpty) {
|
if (comments.isEmpty) {
|
||||||
return Text('No comments');
|
return Text('No comments');
|
||||||
}
|
}
|
||||||
|
@ -176,10 +190,26 @@ class StatusControl extends StatelessWidget {
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
|
if (entry.parentId.isEmpty)
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () async {
|
||||||
|
await getIt<EntryManagerService>()
|
||||||
|
.refreshPost(widget.originalItem)
|
||||||
|
.andThenSuccessAsync((newItem) async => setState(() {
|
||||||
|
print('Updated item');
|
||||||
|
item = newItem;
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
child: Center(
|
||||||
|
child: Text('Load All'),
|
||||||
|
),
|
||||||
|
),
|
||||||
Icon(Icons.subdirectory_arrow_right),
|
Icon(Icons.subdirectory_arrow_right),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: comments.map((c) => StatusControl(item: c)).toList(),
|
children: comments
|
||||||
|
.map((c) => StatusControl(originalItem: c))
|
||||||
|
.toList(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -44,14 +44,18 @@ class FriendicaClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureResult<List<TimelineEntry>, ExecError> getTimeline(
|
FutureResult<List<TimelineEntry>, ExecError> getTimeline(
|
||||||
{required TimelineIdentifiers type, int limit = 20}) async {
|
{required TimelineIdentifiers type,
|
||||||
_logger.finest(() => 'Getting home timeline limit $limit');
|
int sinceId = 0,
|
||||||
|
int limit = 100}) async {
|
||||||
final String timelinePath = _typeToTimelinePath(type);
|
final String timelinePath = _typeToTimelinePath(type);
|
||||||
final String timelineQPs = _typeToTimelineQueryParameters(type);
|
final String timelineQPs = _typeToTimelineQueryParameters(type);
|
||||||
final baseUrl = 'https://$serverName/api/v1/timelines/$timelinePath';
|
final baseUrl = 'https://$serverName/api/v1/timelines/$timelinePath';
|
||||||
final pagingData = 'limit=$limit';
|
final pagingData =
|
||||||
|
sinceId == 0 ? 'limit=$limit' : 'since_id=$sinceId&limit=$limit';
|
||||||
final url = '$baseUrl?$pagingData&$timelineQPs';
|
final url = '$baseUrl?$pagingData&$timelineQPs';
|
||||||
final request = Uri.parse(url);
|
final request = Uri.parse(url);
|
||||||
|
_logger.finest(
|
||||||
|
() => 'Getting home timeline limit $limit since $sinceId : $url');
|
||||||
return (await _getApiListRequest(request).andThenSuccessAsync(
|
return (await _getApiListRequest(request).andThenSuccessAsync(
|
||||||
(postsJson) async => postsJson
|
(postsJson) async => postsJson
|
||||||
.map((json) => TimelineEntryMastodonExtensions.fromJson(json))
|
.map((json) => TimelineEntryMastodonExtensions.fromJson(json))
|
||||||
|
|
|
@ -8,6 +8,8 @@ class Timeline {
|
||||||
int _lowestStatusId = 0;
|
int _lowestStatusId = 0;
|
||||||
int _highestStatusId = 0;
|
int _highestStatusId = 0;
|
||||||
|
|
||||||
|
int get highestStatusId => _highestStatusId;
|
||||||
|
|
||||||
Timeline(this.id, {List<EntryTreeItem>? initialPosts}) {
|
Timeline(this.id, {List<EntryTreeItem>? initialPosts}) {
|
||||||
if (initialPosts != null) {
|
if (initialPosts != null) {
|
||||||
addPosts(initialPosts);
|
addPosts(initialPosts);
|
||||||
|
|
|
@ -75,7 +75,7 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||||
child: ListView.separated(
|
child: ListView.separated(
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
print('Building item: $index');
|
print('Building item: $index');
|
||||||
return StatusControl(item: items[index]);
|
return StatusControl(originalItem: items[index]);
|
||||||
},
|
},
|
||||||
separatorBuilder: (context, index) => Divider(),
|
separatorBuilder: (context, index) => Divider(),
|
||||||
itemCount: items.length,
|
itemCount: items.length,
|
||||||
|
|
|
@ -17,7 +17,7 @@ class EntryManagerService extends ChangeNotifier {
|
||||||
final Map<String, EntryTreeItem> _allComments = {};
|
final Map<String, EntryTreeItem> _allComments = {};
|
||||||
|
|
||||||
FutureResult<List<EntryTreeItem>, ExecError> updateTimeline(
|
FutureResult<List<EntryTreeItem>, ExecError> updateTimeline(
|
||||||
TimelineIdentifiers type) async {
|
TimelineIdentifiers type, int highestId) async {
|
||||||
_logger.fine(() => 'Updating timeline');
|
_logger.fine(() => 'Updating timeline');
|
||||||
final auth = getIt<AuthService>();
|
final auth = getIt<AuthService>();
|
||||||
final clientResult = auth.currentClient;
|
final clientResult = auth.currentClient;
|
||||||
|
@ -27,7 +27,8 @@ class EntryManagerService extends ChangeNotifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
final client = clientResult.value;
|
final client = clientResult.value;
|
||||||
final itemsResult = await client.getTimeline(type: type);
|
final itemsResult =
|
||||||
|
await client.getTimeline(type: type, sinceId: highestId);
|
||||||
final myHandle = client.credentials.username;
|
final myHandle = client.credentials.username;
|
||||||
if (itemsResult.isFailure) {
|
if (itemsResult.isFailure) {
|
||||||
_logger.severe('Error getting timeline: ${itemsResult.error}');
|
_logger.severe('Error getting timeline: ${itemsResult.error}');
|
||||||
|
@ -50,21 +51,30 @@ class EntryManagerService extends ChangeNotifier {
|
||||||
FriendicaClient? client,
|
FriendicaClient? client,
|
||||||
) async {
|
) async {
|
||||||
final updatedPosts = <EntryTreeItem>[];
|
final updatedPosts = <EntryTreeItem>[];
|
||||||
for (final t in items) {
|
for (final item in items) {
|
||||||
late EntryTreeItem entry;
|
late EntryTreeItem entry;
|
||||||
final isMine = t.author == myHandle;
|
final isMine = item.author == myHandle;
|
||||||
if (t.parentAuthor.isEmpty) {
|
if (item.parentAuthor.isEmpty) {
|
||||||
entry = _posts.putIfAbsent(
|
entry = _posts.putIfAbsent(item.id,
|
||||||
t.id, () => EntryTreeItem(t, isMine: isMine, isOrphaned: false));
|
() => EntryTreeItem(item, isMine: isMine, isOrphaned: false));
|
||||||
updatedPosts.add(entry);
|
updatedPosts.add(entry);
|
||||||
} else {
|
} else {
|
||||||
final parent = _posts[t.parentId];
|
final parentPost = _posts[item.parentId];
|
||||||
bool newEntry = false;
|
bool newEntry = false;
|
||||||
entry = _allComments.putIfAbsent(t.id, () {
|
entry = _allComments.putIfAbsent(item.id, () {
|
||||||
newEntry = true;
|
newEntry = true;
|
||||||
return EntryTreeItem(t, isMine: isMine, isOrphaned: parent == null);
|
return EntryTreeItem(
|
||||||
|
item,
|
||||||
|
isMine: isMine,
|
||||||
|
isOrphaned: parentPost == null,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
parent?.addChild(entry);
|
|
||||||
|
if (parentPost != null) {
|
||||||
|
parentPost.addChild(entry);
|
||||||
|
updatedPosts.add(parentPost);
|
||||||
|
}
|
||||||
|
|
||||||
if (newEntry && entry.isOrphaned) {
|
if (newEntry && entry.isOrphaned) {
|
||||||
_orphanedComments.add(entry);
|
_orphanedComments.add(entry);
|
||||||
}
|
}
|
||||||
|
@ -77,6 +87,7 @@ class EntryManagerService extends ChangeNotifier {
|
||||||
if (post != null) {
|
if (post != null) {
|
||||||
c.isOrphaned = false;
|
c.isOrphaned = false;
|
||||||
post.addChild(c);
|
post.addChild(c);
|
||||||
|
updatedPosts.add(post);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,6 +116,37 @@ class EntryManagerService extends ChangeNotifier {
|
||||||
return updatedPosts;
|
return updatedPosts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FutureResult<EntryTreeItem, ExecError> refreshPost(EntryTreeItem item) async {
|
||||||
|
_logger.finest('Refreshing post: ${item.id}');
|
||||||
|
final auth = getIt<AuthService>();
|
||||||
|
final clientResult = auth.currentClient;
|
||||||
|
if (clientResult.isFailure) {
|
||||||
|
_logger.severe('Error getting Friendica client: ${clientResult.error}');
|
||||||
|
return clientResult.errorCast();
|
||||||
|
}
|
||||||
|
|
||||||
|
final client = clientResult.value;
|
||||||
|
final result = await client
|
||||||
|
.getPostOrComment(item.id, fullContext: true)
|
||||||
|
.andThenSuccessAsync((items) async {
|
||||||
|
await processNewItems(items, client.credentials.username, null);
|
||||||
|
});
|
||||||
|
|
||||||
|
return result.mapValue((_) {
|
||||||
|
_logger.finest('${item.id} post updated');
|
||||||
|
notifyListeners();
|
||||||
|
return _posts[item.id]!;
|
||||||
|
}).mapError(
|
||||||
|
(error) {
|
||||||
|
_logger.finest('${item.id} error updating: $error');
|
||||||
|
return ExecError(
|
||||||
|
type: ErrorType.localError,
|
||||||
|
message: error.toString(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
FutureResult<EntryTreeItem, ExecError> toggleFavorited(
|
FutureResult<EntryTreeItem, ExecError> toggleFavorited(
|
||||||
String id, bool newStatus,
|
String id, bool newStatus,
|
||||||
{bool notify = false}) async {
|
{bool notify = false}) async {
|
||||||
|
|
|
@ -27,9 +27,10 @@ class TimelineManager extends ChangeNotifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> refreshTimeline(TimelineIdentifiers type) async {
|
Future<void> refreshTimeline(TimelineIdentifiers type) async {
|
||||||
(await getIt<EntryManagerService>().updateTimeline(type)).match(
|
final timeline = cachedTimelines.putIfAbsent(type, () => Timeline(type));
|
||||||
onSuccess: (posts) {
|
(await getIt<EntryManagerService>()
|
||||||
final timeline = cachedTimelines.putIfAbsent(type, () => Timeline(type));
|
.updateTimeline(type, timeline.highestStatusId))
|
||||||
|
.match(onSuccess: (posts) {
|
||||||
_logger.finest('Posts returned for adding to $type: ${posts.length}');
|
_logger.finest('Posts returned for adding to $type: ${posts.length}');
|
||||||
timeline.addPosts(posts);
|
timeline.addPosts(posts);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
|
Loading…
Reference in a new issue