Skip to content

Commit

Permalink
TW-1480: Update Chat condition has no messages since creation
Browse files Browse the repository at this point in the history
  • Loading branch information
nqhhdev authored and hoangdat committed Mar 1, 2024
1 parent 65830cc commit bd30adf
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 23 deletions.
59 changes: 43 additions & 16 deletions lib/pages/chat/chat.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:fluffychat/pages/chat/chat_actions.dart';
import 'package:fluffychat/pages/chat/chat_view_style.dart';
import 'package:fluffychat/presentation/mixins/handle_clipboard_action_mixin.dart';
import 'package:fluffychat/presentation/mixins/paste_image_mixin.dart';
import 'package:fluffychat/presentation/model/chat/view_event_list_ui_state.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/filtered_timeline_extension.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart';
import 'package:fluffychat/utils/extension/global_key_extension.dart';
Expand Down Expand Up @@ -145,16 +146,16 @@ class ChatController extends State<Chat>
final composerDebouncer =
Debouncer<String>(const Duration(milliseconds: 100), initialValue: '');

bool get isEmptyChat =>
bool get hasNoMessageEvents =>
timeline != null &&
!timeline!.events.any(
(event) => {
EventTypes.Message,
EventTypes.Sticker,
EventTypes.Encrypted,
EventTypes.CallInvite,
}.contains(event.type),
);
!timeline!.events.where((event) => event.isVisibleInGui).any(
(event) => {
EventTypes.Message,
EventTypes.Sticker,
EventTypes.Encrypted,
EventTypes.CallInvite,
}.contains(event.type),
);

final AutoScrollController scrollController = AutoScrollController();

Expand All @@ -171,6 +172,9 @@ class ChatController extends State<Chat>

final ValueNotifier<DateTime?> stickyTimestampNotifier = ValueNotifier(null);

final ValueNotifier<ViewEventListUIState> openingChatViewStateNotifier =
ValueNotifier(ViewEventListInitial());

final FocusSuggestionController _focusSuggestionController =
FocusSuggestionController();

Expand Down Expand Up @@ -310,11 +314,15 @@ class ChatController extends State<Chat>

EmojiPickerType emojiPickerType = EmojiPickerType.keyboard;

void requestHistory() async {
Future<void> requestHistory({
int? historyCount,
}) async {
if (!timeline!.canRequestHistory) return;
Logs().v('Chat::requestHistory(): Requesting history...');
try {
await timeline!.requestHistory(historyCount: _loadHistoryCount);
return timeline!.requestHistory(
historyCount: historyCount ?? _loadHistoryCount,
);
} catch (err) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
Expand All @@ -327,7 +335,7 @@ class ChatController extends State<Chat>
}
}

void _updateScrollController() {
void _updateScrollController() async {
if (!mounted) {
return;
}
Expand All @@ -345,7 +353,7 @@ class ChatController extends State<Chat>
scrollController.position.maxScrollExtent ||
scrollController.position.pixels + _isPortionAvailableToScroll ==
scrollController.position.maxScrollExtent) {
requestHistory();
await requestHistory();
}
}

Expand Down Expand Up @@ -389,10 +397,11 @@ class ChatController extends State<Chat>
}

void _tryLoadTimeline() async {
_updateOpeningChatViewStateNotifier(ViewEventListLoading());
loadTimelineFuture = _getTimeline();
try {
await loadTimelineFuture;
_listenRequestHistory();
await _tryRequestHistory();
final fullyRead = room?.fullyRead;
if (fullyRead == null || fullyRead.isEmpty || fullyRead == '') {
setReadMarker();
Expand Down Expand Up @@ -1636,7 +1645,7 @@ class ChatController extends State<Chat>
_currentChatScrollState = ChatScrollState.scrolling;
}

void _listenRequestHistory() {
Future<void> _tryRequestHistory() async {
if (timeline == null) return;

final allMembershipEvents = timeline!.events.every(
Expand All @@ -1650,7 +1659,24 @@ class ChatController extends State<Chat>
_defaultEventCountDisplay;

if (allMembershipEvents || canRequestHistory) {
requestHistory();
try {
await requestHistory(historyCount: _defaultEventCountDisplay);
} catch (e) {
Logs().e(
'Chat::_tryRequestHistory():: Error - $e',
);
}
_updateOpeningChatViewStateNotifier(ViewEventListSuccess());
}
}

void _updateOpeningChatViewStateNotifier(ViewEventListUIState state) {
try {
openingChatViewStateNotifier.value = state;
} on FlutterError catch (e) {
Logs().e(
'Chat::_updateViewEventListNotifier():: FlutterError - $e',
);
}
}

Expand Down Expand Up @@ -1706,6 +1732,7 @@ class ChatController extends State<Chat>
sendController.dispose();
suggestionsController.dispose();
stickyTimestampNotifier.dispose();
openingChatViewStateNotifier.dispose();
super.dispose();
}

Expand Down
2 changes: 1 addition & 1 deletion lib/pages/chat/chat_event_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class ChatEventList extends StatelessWidget {
thisEventsKeyMap[events[i].eventId] = i;
}

if (controller.isEmptyChat) {
if (controller.hasNoMessageEvents) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expand Down
20 changes: 14 additions & 6 deletions lib/pages/chat/chat_view_body.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'package:fluffychat/pages/chat/events/message_content_mixin.dart';
import 'package:fluffychat/pages/chat/chat_pinned_events/pinned_events_view.dart';
import 'package:fluffychat/pages/chat/sticky_timestamp_widget.dart';
import 'package:fluffychat/pages/chat/tombstone_display.dart';
import 'package:fluffychat/presentation/model/chat/view_event_list_ui_state.dart';
import 'package:fluffychat/utils/date_time_extension.dart';
import 'package:fluffychat/widgets/connection_status_header.dart';
import 'package:fluffychat/widgets/matrix.dart';
Expand Down Expand Up @@ -51,14 +52,21 @@ class ChatViewBody extends StatelessWidget with MessageContentMixin {
Expanded(
child: GestureDetector(
onTap: controller.clearSingleSelectedEvent,
child: Builder(
builder: (context) {
if (controller.timeline == null) {
child: ValueListenableBuilder(
valueListenable:
controller.openingChatViewStateNotifier,
builder: (context, viewState, __) {
if (viewState is ViewEventListLoading) {
return const ChatLoadingView();
}
return ChatEventList(
controller: controller,
);

if (viewState is ViewEventListSuccess) {
return ChatEventList(
controller: controller,
);
}

return const SizedBox.shrink();
},
),
),
Expand Down
21 changes: 21 additions & 0 deletions lib/presentation/model/chat/view_event_list_ui_state.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import 'package:equatable/equatable.dart';

abstract class ViewEventListUIState with EquatableMixin {
@override
List<Object?> get props => [];
}

class ViewEventListInitial extends ViewEventListUIState {
@override
List<Object?> get props => [];
}

class ViewEventListLoading extends ViewEventListUIState {
@override
List<Object?> get props => [];
}

class ViewEventListSuccess extends ViewEventListUIState {
@override
List<Object?> get props => [];
}

0 comments on commit bd30adf

Please sign in to comment.