kopia lustrzana https://gitlab.com/mysocialportal/relatica
Add initial likes/refresh viewing capability
rodzic
089fca1790
commit
a8ef7bb670
|
@ -172,17 +172,24 @@ class _InteractionsBarControlState extends State<InteractionsBarControl> {
|
|||
Row(
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: likes == 0 ? null : () {},
|
||||
onPressed: likes == 0
|
||||
? null
|
||||
: () {
|
||||
context.push('/likes/${widget.entry.id}');
|
||||
},
|
||||
child: Text('$likes likes'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: reshares == 0 ? null : () {},
|
||||
onPressed: reshares == 0
|
||||
? null
|
||||
: () {
|
||||
context.push('/reshares/${widget.entry.id}');
|
||||
},
|
||||
child: Text('$reshares reshares'),
|
||||
),
|
||||
Text('$comments comments'),
|
||||
],
|
||||
),
|
||||
Text('$likes likes, $reshares reshares, $comments comments'),
|
||||
Row(children: [
|
||||
IconButton(
|
||||
onPressed:
|
||||
|
|
|
@ -16,6 +16,7 @@ import 'services/direct_message_service.dart';
|
|||
import 'services/entry_manager_service.dart';
|
||||
import 'services/gallery_service.dart';
|
||||
import 'services/hashtag_service.dart';
|
||||
import 'services/interactions_manager.dart';
|
||||
import 'services/media_upload_attachment_helper.dart';
|
||||
import 'services/network_status_service.dart';
|
||||
import 'services/notifications_manager.dart';
|
||||
|
@ -55,7 +56,9 @@ Future<void> dependencyInjectionInitialization() async {
|
|||
galleryService.getGalleries();
|
||||
getIt.registerLazySingleton<DirectMessageService>(
|
||||
() => DirectMessageService());
|
||||
getIt.registerLazySingleton(() => NetworkStatusService());
|
||||
getIt.registerLazySingleton<NetworkStatusService>(
|
||||
() => NetworkStatusService());
|
||||
getIt.registerLazySingleton<InteractionsManager>(() => InteractionsManager());
|
||||
|
||||
await secretsService.initialize().andThenSuccessAsync((credentials) async {
|
||||
if (credentials.isEmpty) {
|
||||
|
|
|
@ -334,6 +334,44 @@ class FriendicaClient {
|
|||
.execErrorCastAsync();
|
||||
}
|
||||
|
||||
// TODO Convert getLikes to using paging for real
|
||||
FutureResult<List<Connection>, ExecError> getLikes(String id) async {
|
||||
_networkStatusService.startInteractionsLoading();
|
||||
final result = (await runCatchingAsync(() async {
|
||||
final url = 'https://$serverName/api/v1/statuses/$id/favourited_by';
|
||||
final request = Uri.parse('$url');
|
||||
_logger.finest(() => 'Getting favorites for status $id');
|
||||
return (await _getApiListRequest(request)
|
||||
.andThenSuccessAsync((jsonArray) async {
|
||||
return jsonArray.data
|
||||
.map((p) => ConnectionMastodonExtensions.fromJson(p))
|
||||
.toList();
|
||||
}));
|
||||
}))
|
||||
.execErrorCastAsync();
|
||||
_networkStatusService.finishInteractionsLoading();
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO Convert getReshares to using paging for real
|
||||
FutureResult<List<Connection>, ExecError> getReshares(String id) async {
|
||||
_networkStatusService.startInteractionsLoading();
|
||||
final result = (await runCatchingAsync(() async {
|
||||
final url = 'https://$serverName/api/v1/statuses/$id/reblogged_by';
|
||||
final request = Uri.parse('$url');
|
||||
_logger.finest(() => 'Getting rebloggers for status $id');
|
||||
return (await _getApiListRequest(request)
|
||||
.andThenSuccessAsync((jsonArray) async {
|
||||
return jsonArray.data
|
||||
.map((p) => ConnectionMastodonExtensions.fromJson(p))
|
||||
.toList();
|
||||
}));
|
||||
}))
|
||||
.execErrorCastAsync();
|
||||
_networkStatusService.finishInteractionsLoading();
|
||||
return result;
|
||||
}
|
||||
|
||||
FutureResult<bool, ExecError> deleteEntryById(String id) async {
|
||||
_logger.finest(() => 'Deleting post/comment $id');
|
||||
final url = 'https://$serverName/api/v1/statuses/$id';
|
||||
|
|
|
@ -13,6 +13,7 @@ import 'services/direct_message_service.dart';
|
|||
import 'services/entry_manager_service.dart';
|
||||
import 'services/gallery_service.dart';
|
||||
import 'services/hashtag_service.dart';
|
||||
import 'services/interactions_manager.dart';
|
||||
import 'services/notifications_manager.dart';
|
||||
import 'services/setting_service.dart';
|
||||
import 'services/timeline_manager.dart';
|
||||
|
@ -79,6 +80,9 @@ class App extends StatelessWidget {
|
|||
),
|
||||
ChangeNotifierProvider<DirectMessageService>(
|
||||
create: (_) => getIt<DirectMessageService>(),
|
||||
),
|
||||
ChangeNotifierProvider<InteractionsManager>(
|
||||
create: (_) => getIt<InteractionsManager>(),
|
||||
)
|
||||
],
|
||||
child: MaterialApp.router(
|
||||
|
|
|
@ -223,7 +223,7 @@ final appRouter = GoRouter(
|
|||
path: '/likes/:id',
|
||||
name: ScreenPaths.likes,
|
||||
builder: (context, state) => InteractionsViewerScreen(
|
||||
entryId: state.params['id']!,
|
||||
statusId: state.params['id']!,
|
||||
type: InteractionType.like,
|
||||
),
|
||||
),
|
||||
|
@ -231,7 +231,7 @@ final appRouter = GoRouter(
|
|||
path: '/reshares/:id',
|
||||
name: ScreenPaths.reshares,
|
||||
builder: (context, state) => InteractionsViewerScreen(
|
||||
entryId: state.params['id']!,
|
||||
statusId: state.params['id']!,
|
||||
type: InteractionType.reshare,
|
||||
),
|
||||
),
|
||||
|
|
|
@ -1,27 +1,84 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:relatica/controls/standard_appbar.dart';
|
||||
import 'package:relatica/models/interaction_type_enum.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:result_monad/result_monad.dart';
|
||||
|
||||
import '../controls/image_control.dart';
|
||||
import '../controls/standard_appbar.dart';
|
||||
import '../controls/status_and_refresh_button.dart';
|
||||
import '../globals.dart';
|
||||
import '../models/connection.dart';
|
||||
import '../models/exec_error.dart';
|
||||
import '../models/interaction_type_enum.dart';
|
||||
import '../routes.dart';
|
||||
import '../services/interactions_manager.dart';
|
||||
import '../services/network_status_service.dart';
|
||||
|
||||
class InteractionsViewerScreen extends StatelessWidget {
|
||||
final String entryId;
|
||||
final String statusId;
|
||||
final InteractionType type;
|
||||
|
||||
const InteractionsViewerScreen({
|
||||
super.key,
|
||||
required this.entryId,
|
||||
required this.statusId,
|
||||
required this.type,
|
||||
});
|
||||
|
||||
List<Connection> getInteractors(InteractionsManager manager) {
|
||||
switch (type) {
|
||||
case InteractionType.like:
|
||||
return manager.getLikes(statusId);
|
||||
case InteractionType.reshare:
|
||||
return manager.getReshares(statusId);
|
||||
}
|
||||
}
|
||||
|
||||
FutureResult<List<Connection>, ExecError> refreshInteractors(
|
||||
InteractionsManager manager) async {
|
||||
switch (type) {
|
||||
case InteractionType.like:
|
||||
return await manager.updateLikesForStatus(statusId);
|
||||
case InteractionType.reshare:
|
||||
return await manager.updateResharesForStatus(statusId);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final nss = getIt<NetworkStatusService>();
|
||||
final manager = context.watch<InteractionsManager>();
|
||||
final connections = getInteractors(manager);
|
||||
return Scaffold(
|
||||
appBar: StandardAppBar.build(context, buildTitle()),
|
||||
appBar: StandardAppBar.build(context, buildTitle(), actions: [
|
||||
StatusAndRefreshButton(
|
||||
valueListenable: nss.interactionsLoadingStatus,
|
||||
refreshFunction: () async => await refreshInteractors(manager),
|
||||
busyColor: Theme.of(context).colorScheme.background,
|
||||
)
|
||||
]),
|
||||
body: Center(
|
||||
child: Column(
|
||||
children: [
|
||||
Text(buildTitle()),
|
||||
],
|
||||
)),
|
||||
child: ListView.separated(
|
||||
itemCount: connections.length,
|
||||
itemBuilder: (context, index) {
|
||||
final connection = connections[index];
|
||||
return ListTile(
|
||||
onTap: () {
|
||||
context.pushNamed(ScreenPaths.userProfile,
|
||||
params: {'id': connection.id});
|
||||
},
|
||||
leading: ImageControl(
|
||||
imageUrl: connection.avatarUrl.toString(),
|
||||
iconOverride: const Icon(Icons.person),
|
||||
width: 32.0,
|
||||
onTap: () => context.pushNamed(ScreenPaths.userProfile,
|
||||
params: {'id': connection.id}),
|
||||
),
|
||||
title: Text('${connection.name} (${connection.handle})'),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (_, __) => const Divider(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:result_monad/result_monad.dart';
|
||||
|
||||
import '../globals.dart';
|
||||
import '../models/connection.dart';
|
||||
import '../models/exec_error.dart';
|
||||
import 'auth_service.dart';
|
||||
|
||||
class InteractionsManager extends ChangeNotifier {
|
||||
static final _logger = Logger('$InteractionsManager');
|
||||
final _likesByStatusId = <String, List<Connection>>{};
|
||||
final _resharesByStatusId = <String, List<Connection>>{};
|
||||
|
||||
List<Connection> getLikes(String statusId) {
|
||||
if (!_likesByStatusId.containsKey(statusId)) {
|
||||
updateLikesForStatus(statusId);
|
||||
return [];
|
||||
}
|
||||
|
||||
return _likesByStatusId[statusId]!;
|
||||
}
|
||||
|
||||
List<Connection> getReshares(String statusId) {
|
||||
if (!_resharesByStatusId.containsKey(statusId)) {
|
||||
updateResharesForStatus(statusId);
|
||||
return [];
|
||||
}
|
||||
|
||||
return _resharesByStatusId[statusId]!;
|
||||
}
|
||||
|
||||
FutureResult<List<Connection>, ExecError> updateLikesForStatus(
|
||||
String statusId) async {
|
||||
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 likesResult = await client.getLikes(statusId);
|
||||
if (likesResult.isSuccess) {
|
||||
_likesByStatusId[statusId] = likesResult.value;
|
||||
notifyListeners();
|
||||
}
|
||||
return likesResult;
|
||||
}
|
||||
|
||||
FutureResult<List<Connection>, ExecError> updateResharesForStatus(
|
||||
String statusId) async {
|
||||
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 resharesResult = await client.getReshares(statusId);
|
||||
if (resharesResult.isSuccess) {
|
||||
_resharesByStatusId[statusId] = resharesResult.value;
|
||||
notifyListeners();
|
||||
}
|
||||
return resharesResult;
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ import 'package:flutter/foundation.dart';
|
|||
|
||||
class NetworkStatusService {
|
||||
final notificationsUpdateStatus = ValueNotifier<bool>(false);
|
||||
final interactionsLoadingStatus = ValueNotifier<bool>(false);
|
||||
final timelineLoadingStatus = ValueNotifier<bool>(false);
|
||||
final imageGalleryLoadingStatus = ValueNotifier<bool>(false);
|
||||
|
||||
|
@ -28,4 +29,12 @@ class NetworkStatusService {
|
|||
void finishGalleryLoading() {
|
||||
imageGalleryLoadingStatus.value = false;
|
||||
}
|
||||
|
||||
void startInteractionsLoading() {
|
||||
interactionsLoadingStatus.value = true;
|
||||
}
|
||||
|
||||
void finishInteractionsLoading() {
|
||||
interactionsLoadingStatus.value = false;
|
||||
}
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue