Skip to content

Commit

Permalink
feat: scroll improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolantean committed Oct 20, 2023
1 parent d1ede4b commit 04abcc0
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 25 deletions.
16 changes: 0 additions & 16 deletions mobile/lib/core/model/message.dart
Original file line number Diff line number Diff line change
Expand Up @@ -56,22 +56,6 @@ class MessageRequest with _$MessageRequest {
_$MessageRequestFromJson(json);
}

extension SupabaseMessageResponseListExtension
on List<SupabaseMessageResponse> {
List<UserMessage> toUserMessageList({required String userId}) => map(
(message) => UserMessage(
alias: message.user?.alias ?? message.sender,
message: Message(
id: message.id,
body: message.body,
sender: message.sender,
createdAt: message.createdAt,
),
isFromCurrentUser: userId == message.sender,
),
).toList();
}

extension MessageListExtension on List<Message> {
List<UserMessage> toUserMessageList({
required List<SupabaseUserResponse> users,
Expand Down
22 changes: 22 additions & 0 deletions mobile/lib/core/model/user_message.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter_template/core/model/message.dart';
import 'package:flutter_template/core/model/user.dart';
import 'package:freezed_annotation/freezed_annotation.dart';

part 'user_message.freezed.dart';
Expand All @@ -19,6 +20,27 @@ class UserMessage with _$UserMessage {

static List<UserMessage> fromJsonList(List<dynamic> json) =>
json.map((e) => UserMessage.fromJson(e)).toList();

static List<UserMessage> fromResponse({
required List<dynamic> json,
required String userId,
}) {
final messageResponse = SupabaseMessageResponse.fromJsonList(json);
return messageResponse
.map(
(message) => UserMessage(
alias: message.user?.alias ?? message.sender,
message: Message(
id: message.id,
body: message.body,
sender: message.sender,
createdAt: message.createdAt,
),
isFromCurrentUser: userId == message.sender,
),
)
.toList();
}
}

Message _messageSerializer(dynamic data) => Message.fromJson(data);
6 changes: 1 addition & 5 deletions mobile/lib/core/source/messages_remote_source.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,7 @@ class MessagesRemoteSourceImpl implements MessagesRemoteSource {
.from('messages')
.select('*, user:sender(id, alias)')
.order('created_at', ascending: true);
// Json to UserMessages
final messageResponse = SupabaseMessageResponse.fromJsonList(response);
return messageResponse.toUserMessageList(
userId: currentUserId,
);
return UserMessage.fromResponse(json: response, userId: currentUserId);
}

@override
Expand Down
47 changes: 43 additions & 4 deletions mobile/lib/ui/home/home_screen.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_template/core/model/user_message.dart';
Expand Down Expand Up @@ -30,10 +31,12 @@ class _HomeContentScreen extends StatefulWidget {

class _HomeContentScreenState extends State<_HomeContentScreen> {
final _textController = TextEditingController();
final _scrollController = ScrollController();

@override
void dispose() {
_textController.dispose();
_scrollController.dispose();
super.dispose();
}

Expand All @@ -52,7 +55,9 @@ class _HomeContentScreenState extends State<_HomeContentScreen> {
Expanded(
child: state.messages.isEmpty
? const _EmptyStateSection()
: _MessagesSection(messages: state.messages),
: _MessagesSection(
messages: state.messages,
scrollController: _scrollController),
),
_TextFieldSection(textController: _textController),
SizedBox(height: 24.h),
Expand Down Expand Up @@ -101,13 +106,46 @@ class _EmptyStateSection extends StatelessWidget {
);
}

class _MessagesSection extends StatelessWidget {
class _MessagesSection extends StatefulWidget {
final List<UserMessage> messages;
final ScrollController scrollController;

const _MessagesSection({
required this.messages,
required this.scrollController,
});

@override
State<_MessagesSection> createState() => _MessagesSectionState();
}

class _MessagesSectionState extends State<_MessagesSection> {
void _scrollDown() {
widget.scrollController.animateTo(
widget.scrollController.position.maxScrollExtent,
duration: Duration(milliseconds: 100),
curve: Curves.fastOutSlowIn,
);
}

@override
void initState() {
super.initState();

SchedulerBinding.instance.addPostFrameCallback((_) {
_scrollDown();
});
}

@override
void didUpdateWidget(covariant _MessagesSection oldWidget) {
super.didUpdateWidget(oldWidget);

SchedulerBinding.instance.addPostFrameCallback((_) {
_scrollDown();
});
}

@override
Widget build(BuildContext context) => RefreshIndicator(
onRefresh: () => context.read<HomeCubit>().refreshMessages(),
Expand All @@ -117,9 +155,10 @@ class _MessagesSection extends StatelessWidget {
),
child: ListView.builder(
physics: const AlwaysScrollableScrollPhysics(),
itemCount: messages.length,
controller: widget.scrollController,
itemCount: widget.messages.length,
itemBuilder: (context, index) {
final userMessage = messages[index];
final userMessage = widget.messages[index];
return MessageBox(
userMessage: userMessage,
uppercaseMessage: context.read<HomeCubit>().uppercaseMessage,
Expand Down

0 comments on commit 04abcc0

Please sign in to comment.