fix: Paginação da Tela de Mensagem

This commit is contained in:
Ivan Antunes 2024-08-12 17:28:18 -03:00
parent 1d72138926
commit 4d26e74ca1
3 changed files with 334 additions and 281 deletions

View File

@ -1,4 +1,7 @@
PODS:
- connectivity_plus (0.0.1):
- Flutter
- FlutterMacOS
- device_info_plus (0.0.1):
- Flutter
- DKImagePickerController/Core (4.3.9):
@ -225,6 +228,7 @@ PODS:
- Flutter
DEPENDENCIES:
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/darwin`)
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
- file_picker (from `.symlinks/plugins/file_picker/ios`)
- firebase_analytics (from `.symlinks/plugins/firebase_analytics/ios`)
@ -271,6 +275,8 @@ SPEC REPOS:
- SwiftyGif
EXTERNAL SOURCES:
connectivity_plus:
:path: ".symlinks/plugins/connectivity_plus/darwin"
device_info_plus:
:path: ".symlinks/plugins/device_info_plus/ios"
file_picker:
@ -313,6 +319,7 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/webview_flutter_wkwebview/ios"
SPEC CHECKSUMS:
connectivity_plus: ddd7f30999e1faaef5967c23d5b6d503d10434db
device_info_plus: 97af1d7e84681a90d0693e63169a5d50e0839a0d
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60

View File

@ -411,7 +411,6 @@ class ApiManager {
ApiCallOptions? options,
http.Client? client,
}) async {
log('makeApiCall -> $params.toString()');
final callOptions = options ??
ApiCallOptions(

View File

@ -1,5 +1,3 @@
// import 'dart:js_interop';
import 'dart:developer';
import 'package:hub/app_state.dart';
@ -14,6 +12,7 @@ import 'package:hub/pages/message_history_page/message_history_page_model.dart';
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:hub/shared/utils/dialog_util.dart';
import 'package:hub/shared/utils/log_util.dart';
import 'package:provider/provider.dart';
@ -21,28 +20,52 @@ class MessageHistoryPageWidget extends StatefulWidget {
const MessageHistoryPageWidget({super.key});
@override
State<MessageHistoryPageWidget> createState() =>
_MessageHistoryPageWidgetState();
State<MessageHistoryPageWidget> createState() => _MessageHistoryPageWidgetState();
}
class _MessageHistoryPageWidgetState extends State<MessageHistoryPageWidget>
with TickerProviderStateMixin {
class _MessageHistoryPageWidgetState extends State<MessageHistoryPageWidget> with TickerProviderStateMixin {
late MessageHistoryPageModel _model;
final scaffoldKey = GlobalKey<ScaffoldState>();
int currentPage = 0;
int totalPage = 0;
late ScrollController _scrollController;
int _pageNumber = 1;
final int _pageSize = 10;
bool _hasData = false;
bool _loading = false;
String _destinyType = "P";
late Future<void> _messageFuture;
List<dynamic> _messageWrap = [];
@override
void initState() {
super.initState();
_model = createModel(context, () => MessageHistoryPageModel());
_model.tabBarController = TabController(
vsync: this,
length: 3,
initialIndex: 1,
)..addListener(() => setState(() {}));
_messageFuture = fetchMessage();
_scrollController = ScrollController()..addListener(() {
if (_scrollController.position.atEdge && _scrollController.position.pixels != 0) {
_loadMore();
}
});
_model.tabBarController = TabController(vsync: this, length: 3, initialIndex: 0)..addListener(() {
if (_model.tabBarController?.index == 0) {
_destinyType = "P";
} else if (_model.tabBarController?.index == 1) {
_destinyType = "A";
} else {
_destinyType = "T";
}
_pageNumber = 1;
_messageWrap = [];
_messageFuture = fetchMessage();
});
_model.textController ??= TextEditingController();
_model.textFieldFocusNode ??= FocusNode();
@ -51,7 +74,7 @@ class _MessageHistoryPageWidgetState extends State<MessageHistoryPageWidget>
@override
void dispose() {
_model.dispose();
_scrollController.dispose();
super.dispose();
}
@ -66,282 +89,306 @@ class _MessageHistoryPageWidgetState extends State<MessageHistoryPageWidget>
return Scaffold(
key: scaffoldKey,
backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
appBar: buildAppBar(context),
body: buildBody(context, _model),
appBar: _appBar(context),
body: _body(context),
);
}
}
PreferredSizeWidget buildAppBar(BuildContext context) {
return AppBar(
backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
automaticallyImplyLeading: false,
leading: FlutterFlowIconButton(
borderColor: Colors.transparent,
borderRadius: 30.0,
borderWidth: 1.0,
buttonSize: 60.0,
icon: Icon(
Icons.keyboard_arrow_left,
color: FlutterFlowTheme.of(context).primaryText,
size: 30.0,
),
onPressed: () async {
context.pop();
},
),
title: Text(
FFLocalizations.of(context).getVariableText(
enText: 'Message History',
ptText: 'Histórico de Mensagens',
),
style: FlutterFlowTheme.of(context).headlineMedium.override(
fontFamily: 'Nunito',
color: FlutterFlowTheme.of(context).primaryText,
fontSize: 17.0,
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey('Nunito'),
),
),
actions: const [],
centerTitle: true,
);
}
Future<ApiCallResponse?> fetchMessage() async {
try {
setState(() => _loading = true);
Widget buildBody(BuildContext context, MessageHistoryPageModel _model) {
return SafeArea(
top: true,
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Align(
alignment: const Alignment(0.0, 0),
child: TabBar(
labelColor: FlutterFlowTheme.of(context).primaryText,
unselectedLabelColor: FlutterFlowTheme.of(context).primaryText,
labelStyle: FlutterFlowTheme.of(context).titleMedium.override(
fontFamily: FlutterFlowTheme.of(context).titleMediumFamily,
fontSize: 13.0,
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey(
FlutterFlowTheme.of(context).titleMediumFamily),
),
unselectedLabelStyle: const TextStyle(),
indicatorColor: FlutterFlowTheme.of(context).primary,
padding: const EdgeInsets.all(4.0),
tabs: [
Tab(
text: FFLocalizations.of(context).getVariableText(
ptText: 'Pessoal',
enText: 'Personal',
),
),
Tab(
text: FFLocalizations.of(context).getVariableText(
enText: 'All',
ptText: 'Todos',
),
),
Tab(
text: FFLocalizations.of(context).getVariableText(
ptText: 'Global',
enText: 'Global',
),
),
],
controller: _model.tabBarController,
onTap: (i) async {
[() async {}, () async {}][i]();
},
),
var response = await PhpGroup.getMessagesCall.call(
devUUID: FFAppState().devUUID.toString(),
userUUID: FFAppState().userUUID.toString(),
cliID: FFAppState().cliUUID.toString(),
atividade: 'getMensagens',
pageSize: _pageSize.toString(),
pageNumber: _pageNumber.toString(),
tipoDestino: _destinyType,
);
final List<dynamic> messages = response.jsonBody['mensagens'] ?? [];
if (messages != null && messages.isNotEmpty) {
setState(() {
_messageWrap.addAll(messages);
_hasData = true;
_loading = false;
});
return response;
}
_showNoMoreDataSnackBar(context);
setState(() {
_hasData = false;
_loading = false;
});
return null;
} catch (e, s) {
DialogUtil.errorDefault(context);
LogUtil.requestAPIFailed("proccessRequest.php", "", "Consulta de Mensagems", e, s);
setState(() {
_hasData = false;
_loading = false;
});
}
}
void _loadMore() {
if (_hasData == true) {
_pageNumber++;
_messageFuture = fetchMessage();
}
}
PreferredSizeWidget _appBar(BuildContext context) {
return AppBar(
backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
automaticallyImplyLeading: false,
leading: FlutterFlowIconButton(
borderColor: Colors.transparent,
borderRadius: 30.0,
borderWidth: 1.0,
buttonSize: 60.0,
icon: Icon(
Icons.keyboard_arrow_left,
color: FlutterFlowTheme.of(context).primaryText,
size: 30.0,
),
Expanded(
child: TabBarView(controller: _model.tabBarController, children: [
buildListView(context, _model, 'P'),
buildListView(context, _model, 'A'),
buildListView(context, _model, 'T'),
])),
].addToStart(const SizedBox(height: 0)),
),
);
}
onPressed: () async {
context.pop();
},
),
title: Text(
FFLocalizations.of(context).getVariableText(
enText: 'Message History',
ptText: 'Histórico de Mensagens',
),
style: FlutterFlowTheme.of(context).headlineMedium.override(
fontFamily: 'Nunito',
color: FlutterFlowTheme.of(context).primaryText,
fontSize: 17.0,
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey('Nunito'),
),
),
actions: const [],
centerTitle: true,
);
}
Widget buildListView(
BuildContext context, MessageHistoryPageModel _model, String DestIndex) {
return Container(
width: double.infinity,
height: double.infinity,
decoration: const BoxDecoration(),
child: FutureBuilder<dynamic>(
future: Future(() async {
var body = {
'devUUID': FFAppState().devUUID.toString(),
'userUUID': FFAppState().userUUID.toString(),
'cliID': FFAppState().cliUUID.toString(),
'atividade': 'getMensagens',
'pageSize': '100',
'pageNumber': '1',
'tipoDestino': DestIndex.toString(),
};
try {
var response = await PhpGroup.getMessagesCall.call(
devUUID: body['devUUID'],
userUUID: body['userUUID'],
cliID: body['cliID'],
atividade: body['atividade'],
pageSize: body['pageSize'],
pageNumber: body['pageNumber'],
tipoDestino: DestIndex,
);
return response.jsonBody;
} catch (error, stack) {
LogUtil.requestAPIFailed('processRequest.php', jsonEncode(body),
'Mensagens não Encontradas', error, stack);
return {'mensagens': [], 'total_rows': 0};
}
}),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: SizedBox(
width: 50.0,
height: 50.0,
child: SpinKitCircle(
color: FlutterFlowTheme.of(context).primary,
size: 50.0,
Widget _body(BuildContext context) {
return SafeArea(
top: true,
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Align(
alignment: const Alignment(0.0, 0),
child: TabBar(
labelColor: FlutterFlowTheme.of(context).primaryText,
unselectedLabelColor: FlutterFlowTheme.of(context).primaryText,
labelStyle: FlutterFlowTheme.of(context).titleMedium.override(
fontFamily: FlutterFlowTheme.of(context).titleMediumFamily,
fontSize: 13.0,
letterSpacing: 0.0,
useGoogleFonts: GoogleFonts.asMap().containsKey(
FlutterFlowTheme.of(context).titleMediumFamily),
),
),
);
}
if (snapshot.hasError == true ||
snapshot.data == null ||
!snapshot.hasData ||
snapshot.hasError) {
return const Center(
child: Text('Erro ao carregar mensagens'),
);
}
final mensagens = snapshot.data!['mensagens'];
final totalRows = snapshot.data!['total_rows'];
if (totalRows == 0 || mensagens == null || mensagens.isEmpty) {
return const Center(
child: Text('Nenhuma mensagem encontrada'),
);
}
return ListView.builder(
itemCount: totalRows,
addAutomaticKeepAlives: false,
addRepaintBoundaries: true,
cacheExtent: 1000.0,
itemBuilder: (BuildContext context, int index) {
return buildListItem(
context,
snapshot.data!['mensagens'][index],
);
},
);
},
),
);
}
Widget buildListItem(BuildContext context, dynamic jsonBody) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 15),
child: Card(
color: FlutterFlowTheme.of(context).primaryBackground,
child: Container(
// height: 100,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 15.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
Icon(
jsonBody['MSG_DESTINO_TP'] == 'T'
? Icons.language
: jsonBody['MSG_DESTINO_TP'] == 'P'
? Icons.person
: Icons.home,
color: FlutterFlowTheme.of(context).primary,
size: 25,
),
Expanded(
child: Text(
jsonBody['MSG_ORIGEM_DESC'].toString(),
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
color: FlutterFlowTheme.of(context).primary,
),
overflow: TextOverflow.fade,
),
),
].divide(const SizedBox(width: 10)),
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
Padding(
padding: const EdgeInsets.only(left: 5),
child: Icon(
Icons.history,
color: FlutterFlowTheme.of(context).customColor6,
size: 15,
),
),
Expanded(
child: Text(
jsonBody['MSG_DATE'].toString(),
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 10,
color:
FlutterFlowTheme.of(context).customColor6,
),
overflow: TextOverflow.ellipsis,
),
),
].divide(const SizedBox(width: 15)),
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
Padding(
padding: const EdgeInsets.only(left: 5),
child: Icon(
Icons.message,
color: FlutterFlowTheme.of(context).customColor6,
size: 15,
),
),
Expanded(
child: Text(
jsonBody['MSG_TEXTO'].toString(),
),
),
].divide(const SizedBox(width: 15)),
),
].divide(const SizedBox(height: 4)),
unselectedLabelStyle: const TextStyle(),
indicatorColor: FlutterFlowTheme.of(context).primary,
padding: const EdgeInsets.all(4.0),
tabs: [
Tab(
text: FFLocalizations.of(context).getVariableText(
ptText: 'Pessoal',
enText: 'Personal',
),
),
].divide(
const SizedBox(height: 8),
Tab(
text: FFLocalizations.of(context).getVariableText(
enText: 'All',
ptText: 'Todos',
),
),
Tab(
text: FFLocalizations.of(context).getVariableText(
ptText: 'Global',
enText: 'Global',
),
),
],
controller: _model.tabBarController,
),
),
if (_hasData == false && _pageNumber <= 1 && _loading == false)
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
Center(
child: Text(
FFLocalizations.of(context).getVariableText(
ptText: "Nenhuma mensagem encontrada!",
enText: "No message found"
)
),
)
],
),
)
else if (_hasData == true || _pageNumber >= 1)
Expanded(
child: FutureBuilder<void>(
future: _messageFuture,
builder: (context, snapshot) {
return ListView.builder(
shrinkWrap: true,
physics: const BouncingScrollPhysics(),
controller: _scrollController,
itemCount: _messageWrap.length,
itemBuilder: (context, index) {
final item = _messageWrap[index];
return _item(context, item);
}
);
},
),
),
if (_hasData == true && _loading == true)
Container(
padding: const EdgeInsets.only(top: 15, bottom: 15),
child: Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(
FlutterFlowTheme.of(context).primary,
),
),
),
)
].addToStart(const SizedBox(height: 0)),
),
);
}
void _showNoMoreDataSnackBar(BuildContext context) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
FFLocalizations.of(context).getVariableText(ptText: "Não há mais dados.", enText: "No more data."),
),
duration: const Duration(seconds: 3),
backgroundColor: FlutterFlowTheme.of(context).primary,
),
);
}
Widget _item(BuildContext context, dynamic jsonBody) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 15),
child: Card(
color: FlutterFlowTheme.of(context).primaryBackground,
child: Container(
// height: 100,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 15.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
Icon(
jsonBody['MSG_DESTINO_TP'] == 'T'
? Icons.language
: jsonBody['MSG_DESTINO_TP'] == 'P'
? Icons.person
: Icons.home,
color: FlutterFlowTheme.of(context).primary,
size: 25,
),
Expanded(
child: Text(
jsonBody['MSG_ORIGEM_DESC'].toString(),
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
color: FlutterFlowTheme.of(context).primary,
),
overflow: TextOverflow.fade,
),
),
].divide(const SizedBox(width: 10)),
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
Padding(
padding: const EdgeInsets.only(left: 5),
child: Icon(
Icons.history,
color: FlutterFlowTheme.of(context).customColor6,
size: 15,
),
),
Expanded(
child: Text(
jsonBody['MSG_DATE'].toString(),
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 10,
color:
FlutterFlowTheme.of(context).customColor6,
),
overflow: TextOverflow.ellipsis,
),
),
].divide(const SizedBox(width: 15)),
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
Padding(
padding: const EdgeInsets.only(left: 5),
child: Icon(
Icons.message,
color: FlutterFlowTheme.of(context).customColor6,
size: 15,
),
),
Expanded(
child: Text(
jsonBody['MSG_TEXTO'].toString(),
),
),
].divide(const SizedBox(width: 15)),
),
].divide(const SizedBox(height: 4)),
),
),
].divide(
const SizedBox(height: 8),
),
),
),
),
),
));
));
}
}