From 4d26e74ca1ba0e48f70d9a446684604e1b89426c Mon Sep 17 00:00:00 2001 From: Ivan Antunes Date: Mon, 12 Aug 2024 17:28:18 -0300 Subject: [PATCH] =?UTF-8?q?fix:=20Pagina=C3=A7=C3=A3o=20da=20Tela=20de=20M?= =?UTF-8?q?ensagem?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ios/Podfile.lock | 7 + lib/backend/api_requests/api_manager.dart | 1 - .../message_history_page_widget.dart | 607 ++++++++++-------- 3 files changed, 334 insertions(+), 281 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 0aa4fbd2..acfbf591 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -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 diff --git a/lib/backend/api_requests/api_manager.dart b/lib/backend/api_requests/api_manager.dart index 14784b1c..8c2cd6ea 100644 --- a/lib/backend/api_requests/api_manager.dart +++ b/lib/backend/api_requests/api_manager.dart @@ -411,7 +411,6 @@ class ApiManager { ApiCallOptions? options, http.Client? client, }) async { - log('makeApiCall -> $params.toString()'); final callOptions = options ?? ApiCallOptions( diff --git a/lib/pages/message_history_page/message_history_page_widget.dart b/lib/pages/message_history_page/message_history_page_widget.dart index 81e48c79..6a4798b2 100644 --- a/lib/pages/message_history_page/message_history_page_widget.dart +++ b/lib/pages/message_history_page/message_history_page_widget.dart @@ -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 createState() => - _MessageHistoryPageWidgetState(); + State createState() => _MessageHistoryPageWidgetState(); } -class _MessageHistoryPageWidgetState extends State - with TickerProviderStateMixin { +class _MessageHistoryPageWidgetState extends State with TickerProviderStateMixin { late MessageHistoryPageModel _model; final scaffoldKey = GlobalKey(); - 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 _messageFuture; + List _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 @override void dispose() { _model.dispose(); - + _scrollController.dispose(); super.dispose(); } @@ -66,282 +89,306 @@ class _MessageHistoryPageWidgetState extends State 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 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 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( - 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( + 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( + 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), + ), ), ), ), - ), - )); + )); + } + } + +