mirror of
https://github.com/krille-chan/fluffychat
synced 2024-09-10 11:45:10 +00:00
chore: Display stories seenByUsers
This commit is contained in:
parent
09f66917e4
commit
7daf34c13e
3 changed files with 88 additions and 6 deletions
|
@ -5,6 +5,7 @@ import 'dart:io';
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:video_player/video_player.dart';
|
||||
|
@ -13,6 +14,8 @@ import 'package:vrouter/vrouter.dart';
|
|||
import 'package:fluffychat/pages/story/story_view.dart';
|
||||
import 'package:fluffychat/utils/matrix_sdk_extensions.dart/client_stories_extension.dart';
|
||||
import 'package:fluffychat/utils/platform_infos.dart';
|
||||
import 'package:fluffychat/utils/room_status_extension.dart';
|
||||
import 'package:fluffychat/widgets/avatar.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
||||
class StoryPage extends StatefulWidget {
|
||||
|
@ -31,8 +34,60 @@ class StoryPageController extends State<StoryPage> {
|
|||
|
||||
final List<Event> events = [];
|
||||
|
||||
Timeline? timeline;
|
||||
|
||||
Event? get currentEvent => index < events.length ? events[index] : null;
|
||||
|
||||
List<User> get currentSeenByUsers {
|
||||
final timeline = this.timeline;
|
||||
final currentEvent = this.currentEvent;
|
||||
if (timeline == null || currentEvent == null) return [];
|
||||
return Matrix.of(context).client.getRoomById(roomId)?.getSeenByUsers(
|
||||
timeline,
|
||||
events,
|
||||
{},
|
||||
eventId: currentEvent.eventId,
|
||||
) ??
|
||||
[];
|
||||
}
|
||||
|
||||
void displaySeenByUsers() => showModalBottomSheet(
|
||||
context: context,
|
||||
builder: (context) => Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(seenByUsersTitle),
|
||||
),
|
||||
body: ListView.builder(
|
||||
itemCount: currentSeenByUsers.length,
|
||||
itemBuilder: (context, i) => ListTile(
|
||||
leading: Avatar(
|
||||
mxContent: currentSeenByUsers[i].avatarUrl,
|
||||
name: currentSeenByUsers[i].calcDisplayname(),
|
||||
),
|
||||
title: Text(currentSeenByUsers[i].calcDisplayname()),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
String get seenByUsersTitle {
|
||||
final seenByUsers = currentSeenByUsers;
|
||||
if (seenByUsers.isEmpty) return '';
|
||||
if (seenByUsers.length == 1) {
|
||||
return L10n.of(context)!.seenByUser(seenByUsers.single.calcDisplayname());
|
||||
}
|
||||
if (seenByUsers.length == 2) {
|
||||
return L10n.of(context)!.seenByUserAndUser(
|
||||
seenByUsers.first.calcDisplayname(),
|
||||
seenByUsers.last.calcDisplayname(),
|
||||
);
|
||||
}
|
||||
return L10n.of(context)!.seenByUserAndCountOthers(
|
||||
seenByUsers.single.calcDisplayname(),
|
||||
seenByUsers.length - 1,
|
||||
);
|
||||
}
|
||||
|
||||
final TextEditingController replyController = TextEditingController();
|
||||
|
||||
static const Duration _step = Duration(milliseconds: 50);
|
||||
|
@ -56,6 +111,13 @@ class StoryPageController extends State<StoryPage> {
|
|||
});
|
||||
}
|
||||
|
||||
bool get isOwnStory {
|
||||
final client = Matrix.of(context).client;
|
||||
final room = client.getRoomById(roomId);
|
||||
if (room == null) return false;
|
||||
return room.ownPowerLevel >= 100;
|
||||
}
|
||||
|
||||
String get roomId => VRouter.of(context).pathParameters['roomid'] ?? '';
|
||||
|
||||
Future<VideoPlayerController> loadVideoController(Event event) async {
|
||||
|
@ -148,7 +210,7 @@ class StoryPageController extends State<StoryPage> {
|
|||
await room.join();
|
||||
await joinedFuture;
|
||||
}
|
||||
final timeline = await room.getTimeline();
|
||||
final timeline = this.timeline = await room.getTimeline();
|
||||
timeline.requestKeys();
|
||||
var events =
|
||||
timeline.events.where((e) => e.type == EventTypes.Message).toList();
|
||||
|
|
|
@ -225,6 +225,27 @@ class StoryView extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
),
|
||||
if (controller.isOwnStory &&
|
||||
controller.currentSeenByUsers.isNotEmpty)
|
||||
Positioned(
|
||||
bottom: 16,
|
||||
left: 16,
|
||||
right: 16,
|
||||
child: SafeArea(
|
||||
child: Center(
|
||||
child: OutlinedButton.icon(
|
||||
onPressed: controller.displaySeenByUsers,
|
||||
icon: const Icon(
|
||||
Icons.visibility_outlined,
|
||||
color: Colors.white70,
|
||||
),
|
||||
label: Text(
|
||||
controller.seenByUsersTitle,
|
||||
style: const TextStyle(color: Colors.white70),
|
||||
),
|
||||
),
|
||||
),
|
||||
)),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
|
@ -69,20 +69,19 @@ extension RoomStatusExtension on Room {
|
|||
}
|
||||
|
||||
List<User> getSeenByUsers(
|
||||
Timeline timeline,
|
||||
List<Event> filteredEvents,
|
||||
Set<String> unfolded,
|
||||
) {
|
||||
Timeline timeline, List<Event> filteredEvents, Set<String> unfolded,
|
||||
{String? eventId}) {
|
||||
if (timeline.events.isEmpty) return [];
|
||||
|
||||
final filteredEvents = timeline.getFilteredEvents(unfolded: unfolded);
|
||||
if (filteredEvents.isEmpty) return [];
|
||||
eventId ??= filteredEvents.first.eventId;
|
||||
|
||||
final lastReceipts = <User>{};
|
||||
// now we iterate the timeline events until we hit the first rendered event
|
||||
for (final event in timeline.events) {
|
||||
lastReceipts.addAll(event.receipts.map((r) => r.user));
|
||||
if (event.eventId == filteredEvents.first.eventId) {
|
||||
if (event.eventId == eventId) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue