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

View File

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

View File

@ -1,5 +1,3 @@
// import 'dart:js_interop';
import 'dart:developer'; import 'dart:developer';
import 'package:hub/app_state.dart'; 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/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:google_fonts/google_fonts.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:hub/shared/utils/log_util.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -21,28 +20,52 @@ class MessageHistoryPageWidget extends StatefulWidget {
const MessageHistoryPageWidget({super.key}); const MessageHistoryPageWidget({super.key});
@override @override
State<MessageHistoryPageWidget> createState() => State<MessageHistoryPageWidget> createState() => _MessageHistoryPageWidgetState();
_MessageHistoryPageWidgetState();
} }
class _MessageHistoryPageWidgetState extends State<MessageHistoryPageWidget> class _MessageHistoryPageWidgetState extends State<MessageHistoryPageWidget> with TickerProviderStateMixin {
with TickerProviderStateMixin {
late MessageHistoryPageModel _model; late MessageHistoryPageModel _model;
final scaffoldKey = GlobalKey<ScaffoldState>(); 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 @override
void initState() { void initState() {
super.initState(); super.initState();
_model = createModel(context, () => MessageHistoryPageModel()); _model = createModel(context, () => MessageHistoryPageModel());
_model.tabBarController = TabController( _messageFuture = fetchMessage();
vsync: this,
length: 3, _scrollController = ScrollController()..addListener(() {
initialIndex: 1, if (_scrollController.position.atEdge && _scrollController.position.pixels != 0) {
)..addListener(() => setState(() {})); _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.textController ??= TextEditingController();
_model.textFieldFocusNode ??= FocusNode(); _model.textFieldFocusNode ??= FocusNode();
@ -51,7 +74,7 @@ class _MessageHistoryPageWidgetState extends State<MessageHistoryPageWidget>
@override @override
void dispose() { void dispose() {
_model.dispose(); _model.dispose();
_scrollController.dispose();
super.dispose(); super.dispose();
} }
@ -66,282 +89,306 @@ class _MessageHistoryPageWidgetState extends State<MessageHistoryPageWidget>
return Scaffold( return Scaffold(
key: scaffoldKey, key: scaffoldKey,
backgroundColor: FlutterFlowTheme.of(context).primaryBackground, backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
appBar: buildAppBar(context), appBar: _appBar(context),
body: buildBody(context, _model), body: _body(context),
); );
} }
}
PreferredSizeWidget buildAppBar(BuildContext context) { Future<ApiCallResponse?> fetchMessage() async {
return AppBar( try {
backgroundColor: FlutterFlowTheme.of(context).primaryBackground, setState(() => _loading = true);
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,
);
}
Widget buildBody(BuildContext context, MessageHistoryPageModel _model) { var response = await PhpGroup.getMessagesCall.call(
return SafeArea( devUUID: FFAppState().devUUID.toString(),
top: true, userUUID: FFAppState().userUUID.toString(),
child: Column( cliID: FFAppState().cliUUID.toString(),
mainAxisSize: MainAxisSize.max, atividade: 'getMensagens',
mainAxisAlignment: MainAxisAlignment.start, pageSize: _pageSize.toString(),
children: [ pageNumber: _pageNumber.toString(),
Align( tipoDestino: _destinyType,
alignment: const Alignment(0.0, 0), );
child: TabBar(
labelColor: FlutterFlowTheme.of(context).primaryText, final List<dynamic> messages = response.jsonBody['mensagens'] ?? [];
unselectedLabelColor: FlutterFlowTheme.of(context).primaryText,
labelStyle: FlutterFlowTheme.of(context).titleMedium.override( if (messages != null && messages.isNotEmpty) {
fontFamily: FlutterFlowTheme.of(context).titleMediumFamily, setState(() {
fontSize: 13.0, _messageWrap.addAll(messages);
letterSpacing: 0.0, _hasData = true;
useGoogleFonts: GoogleFonts.asMap().containsKey( _loading = false;
FlutterFlowTheme.of(context).titleMediumFamily), });
),
unselectedLabelStyle: const TextStyle(), return response;
indicatorColor: FlutterFlowTheme.of(context).primary, }
padding: const EdgeInsets.all(4.0),
tabs: [ _showNoMoreDataSnackBar(context);
Tab(
text: FFLocalizations.of(context).getVariableText( setState(() {
ptText: 'Pessoal', _hasData = false;
enText: 'Personal', _loading = false;
), });
), return null;
Tab( } catch (e, s) {
text: FFLocalizations.of(context).getVariableText( DialogUtil.errorDefault(context);
enText: 'All', LogUtil.requestAPIFailed("proccessRequest.php", "", "Consulta de Mensagems", e, s);
ptText: 'Todos', setState(() {
), _hasData = false;
), _loading = false;
Tab( });
text: FFLocalizations.of(context).getVariableText( }
ptText: 'Global', }
enText: 'Global',
), void _loadMore() {
), if (_hasData == true) {
], _pageNumber++;
controller: _model.tabBarController, _messageFuture = fetchMessage();
onTap: (i) async { }
[() async {}, () async {}][i](); }
},
), 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( onPressed: () async {
child: TabBarView(controller: _model.tabBarController, children: [ context.pop();
buildListView(context, _model, 'P'), },
buildListView(context, _model, 'A'), ),
buildListView(context, _model, 'T'), title: Text(
])), FFLocalizations.of(context).getVariableText(
].addToStart(const SizedBox(height: 0)), 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( Widget _body(BuildContext context) {
BuildContext context, MessageHistoryPageModel _model, String DestIndex) { return SafeArea(
return Container( top: true,
width: double.infinity, child: Column(
height: double.infinity, mainAxisSize: MainAxisSize.max,
decoration: const BoxDecoration(), mainAxisAlignment: MainAxisAlignment.start,
child: FutureBuilder<dynamic>( children: [
future: Future(() async { Align(
var body = { alignment: const Alignment(0.0, 0),
'devUUID': FFAppState().devUUID.toString(), child: TabBar(
'userUUID': FFAppState().userUUID.toString(), labelColor: FlutterFlowTheme.of(context).primaryText,
'cliID': FFAppState().cliUUID.toString(), unselectedLabelColor: FlutterFlowTheme.of(context).primaryText,
'atividade': 'getMensagens', labelStyle: FlutterFlowTheme.of(context).titleMedium.override(
'pageSize': '100', fontFamily: FlutterFlowTheme.of(context).titleMediumFamily,
'pageNumber': '1', fontSize: 13.0,
'tipoDestino': DestIndex.toString(), letterSpacing: 0.0,
}; useGoogleFonts: GoogleFonts.asMap().containsKey(
try { FlutterFlowTheme.of(context).titleMediumFamily),
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,
), ),
), unselectedLabelStyle: const TextStyle(),
); indicatorColor: FlutterFlowTheme.of(context).primary,
} padding: const EdgeInsets.all(4.0),
if (snapshot.hasError == true || tabs: [
snapshot.data == null || Tab(
!snapshot.hasData || text: FFLocalizations.of(context).getVariableText(
snapshot.hasError) { ptText: 'Pessoal',
return const Center( enText: 'Personal',
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)),
), ),
), ),
].divide( Tab(
const SizedBox(height: 8), 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),
),
), ),
), ),
), ),
), ));
)); }
} }