Skip to content

Commit

Permalink
TW-578: improve sync room status
Browse files Browse the repository at this point in the history
  • Loading branch information
Julian KOUNE committed Oct 6, 2023
1 parent 2a16ca7 commit 396af5d
Show file tree
Hide file tree
Showing 8 changed files with 327 additions and 109 deletions.
18 changes: 0 additions & 18 deletions assets/l10n/intl_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -2546,24 +2546,6 @@
"min": {}
}
},
"onlineDayAgo": "online {day} day ago",
"@onlineDayAgo": {
"placeholders": {
"day": {}
}
},
"onlineWeekAgo": "online {week} week ago",
"@onlineWeekAgo": {
"placeholders": {
"week": {}
}
},
"onlineMonthAgo": "online {month} month ago",
"@onlineMonthAgo": {
"placeholders": {
"month": {}
}
},
"noMessageHereYet": "No message here yet...",
"sendMessageGuide": "Send a message or tap on the greeting bellow.",
"youCreatedGroupChat": "You created a Group chat",
Expand Down
223 changes: 174 additions & 49 deletions lib/pages/chat/chat_app_bar_title.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:fluffychat/pages/chat/chat_app_bar_title_style.dart';
import 'package:fluffychat/utils/common_helper.dart';
import 'package:fluffychat/utils/room_status_extension.dart';
import 'package:fluffychat/utils/string_extension.dart';
import 'package:flutter/material.dart';
Expand All @@ -10,14 +11,15 @@ import 'package:fluffychat/pages/user_bottom_sheet/user_bottom_sheet.dart';
import 'package:fluffychat/utils/adaptive_bottom_sheet.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
import 'package:fluffychat/widgets/avatar/avatar.dart';
import 'package:rxdart/rxdart.dart';

class ChatAppBarTitle extends StatelessWidget {
final Widget? actions;
final Room? room;
final List<Event> selectedEvents;
final bool isArchived;
final TextEditingController sendController;
final Stream<ConnectivityResult> getStreamInstance;
final Stream<ConnectivityResult> connectivityResultStream;
final VoidCallback onPushDetails;
final String? roomName;

Expand All @@ -29,7 +31,7 @@ class ChatAppBarTitle extends StatelessWidget {
required this.selectedEvents,
required this.isArchived,
required this.sendController,
required this.getStreamInstance,
required this.connectivityResultStream,
required this.onPushDetails,
}) : super(key: key);

Expand Down Expand Up @@ -98,70 +100,193 @@ class ChatAppBarTitle extends StatelessWidget {
overflow: TextOverflow.ellipsis,
style: ChatAppBarTitleStyle.appBarTitleStyle(context),
),
_buildStatusContent(context, room!),
_ChatAppBarStatusContent(
connectivityResultStream: connectivityResultStream,
room: room!,
),
],
),
),
],
),
);
}
}

StreamBuilder<ConnectivityResult> _buildStatusContent(
BuildContext context,
Room room,
) {
final TextStyle? statusTextStyle =
ChatAppBarTitleStyle.statusTextStyle(context);
class _ChatAppBarStatusContent extends StatelessWidget {
const _ChatAppBarStatusContent({
required this.connectivityResultStream,
required this.room,
});

final Stream<ConnectivityResult> connectivityResultStream;
final Room room;

@override
Widget build(BuildContext context) {
if (room.isDirectChat) {
return _DirectChatAppBarStatusContent(
connectivityResultStream: connectivityResultStream,
room: room,
);
}

return _GroupChatAppBarStatusContent(
connectivityResultStream: connectivityResultStream,
room: room,
);
}
}

class _DirectChatAppBarStatusContent extends StatelessWidget {
const _DirectChatAppBarStatusContent({
required this.connectivityResultStream,
required this.room,
});

final Stream<ConnectivityResult> connectivityResultStream;
final Room room;

@override
Widget build(BuildContext context) {
CachedPresence? directChatPresence = room.directChatPresence;
return FutureBuilder<GetPresenceResponse>(
future: room.client.getPresence(room.directChatMatrixID!),
builder: (context, futureSnapshot) {
if (futureSnapshot.hasData) {
directChatPresence = CachedPresence.fromPresenceResponse(
futureSnapshot.data!,
room.directChatMatrixID!,
);
}
return StreamBuilder<List>(
stream: CombineLatestStream.list(
[connectivityResultStream, room.directChatPresenceStream],
),
builder: (context, snapshot) {
final connectivityResult = tryCast<ConnectivityResult>(
snapshot.data?[0],
fallback: ConnectivityResult.none,
);
directChatPresence = tryCast<CachedPresence>(
snapshot.data?[1],
fallback: directChatPresence,
);
if (snapshot.hasData &&
connectivityResult == ConnectivityResult.none) {
return _ChatAppBarTitleText(text: L10n.of(context)!.noConnection);
}
final typingText = room.getLocalizedTypingText(context);
if (typingText.isEmpty) {
return _ChatAppBarTitleText(
text: room
.getLocalizedStatus(context, presence: directChatPresence)
.capitalize(context),
);
} else {
return _ChatAppBarTitleTyping(typingText: typingText);
}
},
);
},
);
}
}

class _GroupChatAppBarStatusContent extends StatelessWidget {
const _GroupChatAppBarStatusContent({
required this.connectivityResultStream,
required this.room,
});

final Stream<ConnectivityResult> connectivityResultStream;
final Room room;

@override
Widget build(BuildContext context) {
return StreamBuilder<ConnectivityResult>(
stream: getStreamInstance,
stream: connectivityResultStream,
builder: (context, snapshot) {
if (snapshot.hasData && snapshot.data == ConnectivityResult.none) {
return Text(
L10n.of(context)!.noConnection,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: statusTextStyle,
);
final connectivityResult = tryCast<ConnectivityResult>(
snapshot.data,
fallback: ConnectivityResult.none,
);

if (snapshot.hasData && connectivityResult == ConnectivityResult.none) {
return _ChatAppBarTitleText(text: L10n.of(context)!.noConnection);
}
final typingText = room.getLocalizedTypingText(context);
if (typingText.isEmpty) {
return Text(
room.getLocalizedStatus(context).capitalize(context),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: statusTextStyle,
return _ChatAppBarTitleText(
text: room.getLocalizedStatus(context).capitalize(context),
);
} else {
return IntrinsicWidth(
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Expanded(
child: Text(
typingText,
maxLines: 1,
overflow: TextOverflow.clip,
style: statusTextStyle,
),
),
SizedBox(
width: 32,
height: 16,
child: Transform.translate(
offset: const Offset(0, -2),
child: LottieBuilder.asset(
'assets/typing-indicator.zip',
fit: BoxFit.fitWidth,
width: 32,
),
),
),
],
),
);
return _ChatAppBarTitleTyping(typingText: typingText);
}
},
);
}
}

class _ChatAppBarTitleText extends StatelessWidget {
const _ChatAppBarTitleText({
required this.text,
});

final String text;

@override
Widget build(BuildContext context) {
final TextStyle? statusTextStyle =
ChatAppBarTitleStyle.statusTextStyle(context);

return Text(
text,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: statusTextStyle,
);
}
}

class _ChatAppBarTitleTyping extends StatelessWidget {
const _ChatAppBarTitleTyping({
required this.typingText,
});

final String typingText;

@override
Widget build(BuildContext context) {
final TextStyle? statusTextStyle =
ChatAppBarTitleStyle.statusTextStyle(context);

return IntrinsicWidth(
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Expanded(
child: Text(
typingText,
maxLines: 1,
overflow: TextOverflow.clip,
style: statusTextStyle,
),
),
SizedBox(
width: 32,
height: 16,
child: Transform.translate(
offset: const Offset(0, -2),
child: LottieBuilder.asset(
'assets/typing-indicator.zip',
fit: BoxFit.fitWidth,
width: 32,
),
),
),
],
),
);
}
}
2 changes: 1 addition & 1 deletion lib/pages/chat/chat_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ class ChatView extends StatelessWidget {
room: controller.room,
isArchived: controller.isArchived,
sendController: controller.sendController,
getStreamInstance: controller
connectivityResultStream: controller
.networkConnectionService
.getStreamInstance(),
actions: _appBarActions(context),
Expand Down
7 changes: 7 additions & 0 deletions lib/utils/common_helper.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
T? tryCast<T>(dynamic value, {T? fallback}) {
if (value != null && value is T) {
return value;
}

return fallback;
}
10 changes: 10 additions & 0 deletions lib/utils/date_time_extension.dart
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,14 @@ extension DateTimeExtension on DateTime {
String getFormattedCurrentDateTime() {
return millisecondsSinceEpoch.toString();
}

bool isLessThanOneHourAgo({DateTime? other}) {
other ??= DateTime.now();
return other.difference(this) < const Duration(hours: 1);
}

bool isLessThanTenHoursAgo({DateTime? other}) {
other ??= DateTime.now();
return other.difference(this) < const Duration(hours: 10);
}
}
Loading

0 comments on commit 396af5d

Please sign in to comment.