Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor + Improve typing indicators #279

Merged
merged 3 commits into from
Jun 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion commet/lib/client/components/component_registry.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import 'package:commet/client/matrix/components/invitation/matrix_invitation_com
import 'package:commet/client/matrix/components/push_notifications/matrix_push_notification_component.dart';
import 'package:commet/client/matrix/components/read_receipts/matrix_read_receipt_component.dart';
import 'package:commet/client/matrix/components/threads/matrix_threads_component.dart';
import 'package:commet/client/matrix/components/typing_indicators/matrix_typing_indicators_component.dart';
import 'package:commet/client/matrix/components/url_preview/matrix_url_preview_component.dart';
import 'package:commet/client/matrix/matrix_client.dart';
import 'package:commet/client/matrix/matrix_room.dart';
Expand All @@ -35,7 +36,8 @@ class ComponentRegistry {
return [
MatrixRoomEmoticonComponent(client, room),
MatrixGifComponent(client, room),
MatrixReadReceiptComponent(client, room)
MatrixReadReceiptComponent(client, room),
MatrixTypingIndicatorsComponent(client, room),
];
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import 'package:commet/client/client.dart';
import 'package:commet/client/components/room_component.dart';
import 'package:commet/client/member.dart';

abstract class TypingIndicatorComponent<R extends Client, T extends Room>
implements RoomComponent<R, T> {
Stream<void> get onTypingUsersUpdated;

List<Member> get typingUsers;

Future<void> setTypingStatus(bool status);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import 'dart:async';

import 'package:commet/client/components/typing_indicators/typing_indicator_component.dart';
import 'package:commet/client/matrix/components/matrix_sync_listener.dart';
import 'package:commet/client/matrix/matrix_client.dart';
import 'package:commet/client/matrix/matrix_member.dart';
import 'package:commet/client/matrix/matrix_room.dart';
import 'package:commet/client/member.dart';
import 'package:matrix/matrix_api_lite/model/sync_update.dart';

class MatrixTypingIndicatorsComponent
implements
TypingIndicatorComponent<MatrixClient, MatrixRoom>,
MatrixRoomSyncListener {
@override
MatrixClient client;
@override
MatrixRoom room;

MatrixTypingIndicatorsComponent(this.client, this.room);

final StreamController<void> _controller = StreamController.broadcast();

@override
onSync(JoinedRoomUpdate update) {
final ephemeral = update.ephemeral;

if (ephemeral == null) {
return;
}

if (ephemeral.any((e) => e.type == "m.typing")) {
_controller.add(null);
}
}

@override
Stream<void> get onTypingUsersUpdated => _controller.stream;

@override
List<Member> get typingUsers => room.matrixRoom.typingUsers
.where((element) => client.self?.identifier != element.id)
.map((e) => MatrixMember(room.matrixRoom.client, e))
.toList();

@override
Future<void> setTypingStatus(bool status) {
return room.matrixRoom.setTyping(status, timeout: 2000);
}
}
11 changes: 0 additions & 11 deletions commet/lib/client/matrix/matrix_room.dart
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,6 @@ class MatrixRoom extends Room {
@override
Iterable<String> get memberIds => _memberIds;

@override
List<Member> get typingPeers => _matrixRoom.typingUsers
.where((element) => client.self?.identifier != element.id)
.map((e) => MatrixMember(_matrixRoom.client, e))
.toList();

@override
String get developerInfo =>
const JsonEncoder.withIndent(' ').convert(_matrixRoom.states);
Expand Down Expand Up @@ -425,11 +419,6 @@ class MatrixRoom extends Room {
await _matrixRoom.setName(newName);
}

@override
Future<void> setTypingStatus(bool typing) async {
await _matrixRoom.setTyping(typing, timeout: 2000);
}

@override
Color getColorOfUser(String userId) {
return MatrixPeer.hashColor(userId);
Expand Down
6 changes: 0 additions & 6 deletions commet/lib/client/room.dart
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,6 @@ abstract class Room {
/// Gets the time of the last known event
DateTime get lastEventTimestamp;

/// Set of peers who are currently typing a message in this room
List<Member> get typingPeers;

/// Debug info for developers
String get developerInfo;

Expand Down Expand Up @@ -116,9 +113,6 @@ abstract class Room {
/// Set a notification push rule
Future<void> setPushRule(PushRule rule);

/// Set the typing status of the current user
Future<void> setTypingStatus(bool typing);

/// Gets the color of a user based on their ID
Color getColorOfUser(String userId);

Expand Down
40 changes: 4 additions & 36 deletions commet/lib/ui/molecules/message_input.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:implicitly_animated_list/implicitly_animated_list.dart';
import 'package:intl/intl.dart';
import 'package:just_the_tooltip/just_the_tooltip.dart';
import 'package:pasteboard/pasteboard.dart';
import 'package:tiamat/tiamat.dart' as tiamat;
Expand Down Expand Up @@ -47,7 +46,7 @@ class MessageInput extends StatefulWidget {
this.addAttachment,
this.onTextUpdated,
this.removeAttachment,
this.typingUsernames,
this.typingIndicatorWidget,
this.availibleEmoticons,
this.availibleStickers,
this.gifComponent,
Expand All @@ -74,7 +73,7 @@ class MessageInput extends StatefulWidget {
final Stream<String>? setInputText;
final bool isProcessing;
final bool enabled;
final List<String>? typingUsernames;
final Widget? typingIndicatorWidget;
final List<EmoticonPack>? availibleEmoticons;
final List<EmoticonPack>? availibleStickers;
final GifComponent? gifComponent;
Expand Down Expand Up @@ -108,16 +107,6 @@ class MessageInputState extends State<MessageInput> {
(int, int)? autoFillRange;
ScrollController autofillScrollController = ScrollController();

String typingUsers(int howMany, String user1, String user2, String user3) =>
Intl.plural(howMany,
one: "$user1 is typing...",
two: "$user1 and $user2 are typing...",
few: "$user1, $user2, and $user3 are typing...",
other: "Several people are typing...",
desc: "Text to display which users are currently typing",
name: "typingUsers",
args: [howMany, user1, user2, user3]);

void unfocus() {
textFocus.unfocus();
}
Expand Down Expand Up @@ -379,7 +368,8 @@ class MessageInputState extends State<MessageInput> {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
typingUsersWidget(),
if (widget.typingIndicatorWidget != null)
widget.typingIndicatorWidget!,
if (widget.interactionType != null) interactionText(),
if (widget.attachments != null && widget.attachments!.isNotEmpty)
displayAttachments(),
Expand Down Expand Up @@ -799,26 +789,4 @@ class MessageInputState extends State<MessageInput> {
onShare: null,
);
}

Widget typingUsersWidget() {
String text = getTypingText();

return Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 4),
child: tiamat.Text.labelLow(text),
));
}

String getTypingText() {
if (widget.typingUsernames?.isEmpty == true) return "";

String user1 = widget.typingUsernames![0];
String user2 =
widget.typingUsernames!.length >= 2 ? widget.typingUsernames![1] : "";
String user3 =
widget.typingUsernames!.length >= 3 ? widget.typingUsernames![2] : "";
return typingUsers(widget.typingUsernames!.length, user1, user2, user3);
}
}
Loading
Loading