소스 검색

beresin account

Yulian 2 달 전
부모
커밋
a8974652fd

+ 6 - 6
lib/main.dart

@@ -252,16 +252,16 @@ class NotificationClass {
     });
   }
 
-  getActiveNotif() async {
-    List<ActiveNotification>? activeNotif = await U.flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()?.getActiveNotifications();
-    return activeNotif;
+  getActiveNotification() async {
+    List<ActiveNotification>? activeNotification = await U.flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()?.getActiveNotifications();
+    return activeNotification;
   }
 
-  startNotification(BuildContext context, {code}) async {
-    final locale = context.locale.toString();
+  startNotification({code}) async {
+    final locale = NavigationService.navigatorKey.currentContext?.locale.toString();
     var token = await U.getFcmToken();
     if (token != null) {
-      Map data = {'token': token, 'language': code ?? locale.toUpperCase()};
+      Map data = {'token': token, 'language': code ?? locale?.toUpperCase()};
       var res = _apiAuthProvider.postData('/api/fcmTokens/register', null, data);
       return res;
     }

+ 10 - 11
lib/src/api/api_auth_provider.dart

@@ -321,7 +321,7 @@ class ApiAuthProvider {
     }
   }
 
-  Future patchData(String path, var data, context, {var params}) async {
+  Future patchData(String path, var data, {var params}) async {
     try {
       Response response = await _dio.patchUri(
         Uri(path: path, queryParameters: params),
@@ -339,26 +339,25 @@ class ApiAuthProvider {
         try {
           final result = await InternetAddress.lookup('google.com');
           if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
-            showError(context, 'errorConnection'.tr());
+            UIService.showError('errorConnection'.tr());
           }
         } on SocketException catch (_) {
-          showError(context, 'noInternet'.tr());
+          UIService.showError('noInternet'.tr());
         }
       } else if (error.response!.statusCode! >= 500) {
-        showError(context, 'errorConnection'.tr());
+        UIService.showError('errorConnection'.tr());
       } else if (error.response?.statusCode == 401) {
-        handlingError(context, 3); //error auth
+        UIService.handlingError(ErrorType.invalidAccount); //error auth
       } else if (error.response?.statusCode == 422) {
         if (error.response?.data['message'] == 'Old Password Not Match.') {
-          showError(context, 'wrongOldPass'.tr());
-        } else if (error.response?.data['message'] ==
-            'New password already in used.') {
-          showError(context, 'alreadyUsePass'.tr());
+          UIService.showError('wrongOldPass'.tr());
+        } else if (error.response?.data['message'] == 'New password already in used.') {
+          UIService.showError('alreadyUsePass'.tr());
         } else {
-          showError(context, error.response?.data['message']);
+          UIService.showError(error.response?.data['message']);
         }
       } else {
-        showError(context, 'errorServer'.tr());
+        UIService.showError('errorServer'.tr());
       }
       return null;
     }

+ 2 - 2
lib/src/layouts/auth/login.dart

@@ -331,7 +331,7 @@ class _LoginPageState extends State<LoginPage> {
       };
     }
     try{
-      var res = await apiAuthProvider.patchData('/api/informants/${tkn['userId']}', p, context);
+      var res = await apiAuthProvider.patchData('/api/informants/${tkn['userId']}', p);
       if (res != null) {
         // print("res $res");
         // context.setLocale(Locale(code));
@@ -643,7 +643,7 @@ class _ForceChgPassPageState extends State<ForceChgPassPage> {
           var data = {'oldPassword': widget.data['password'], 'password': newPassword.trim()};
 
           try {
-            var res = await apiAuthProvider.patchData('/api/informants/${tokenData['userId']}/changePassword', data, context);
+            var res = await apiAuthProvider.patchData('/api/informants/${tokenData['userId']}/changePassword', data);
             if (res != null) {
               String password = tokenData['related'] && tokenData['tenantCode'] != null && tokenData['tenantCode'] != '' ?  tokenData['tenantCode'] + ' ${data['password']}' : data['password'];
 

+ 19 - 15
lib/src/layouts/components/auto_login.dart

@@ -13,6 +13,7 @@ import 'package:telnow_mobile_new/src/model/token/token.dart';
 import 'package:flutter/material.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:telnow_mobile_new/src/utils/U.dart';
+import 'package:telnow_mobile_new/src/utils/ui_service.dart';
 
 @RoutePage()
 class AutoLoginPage extends StatefulWidget {
@@ -72,8 +73,9 @@ class _AutoLoginPageState extends State<AutoLoginPage> {
       debugPrint("invalid param: $e");
       redirectToLoginPage = true;
       Future.delayed(Duration.zero, (){
-        context.router.removeLast();
-        context.navigateToPath("/app/${U.getAccessCode()}");
+        UIService.navigateNamed("/app/${U.getAccessCode()}");
+        // context.router.removeLast();
+        // context.navigateToPath("/app/${U.getAccessCode()}");
       });
     }
   }
@@ -84,8 +86,8 @@ class _AutoLoginPageState extends State<AutoLoginPage> {
     try {
       Token token = await apiAuthRepository.postLoginUser(LoginBody(dData["username"]!.trim(), dData["password"]!.trim(), "password"));
       if (token.error != null) {
-        closeLoading(context);
-        showError(context, token.error);
+        UIService.closeLoading();
+        UIService.showError(token.error.toString());
         setState(() {
           loading = false;
           invalidUserLogin = true;
@@ -102,7 +104,7 @@ class _AutoLoginPageState extends State<AutoLoginPage> {
       // print(jwt);
       var user = await apiAuthProvider.getData('/api/informants/${jwt['userId']}', null);
       if(user != null){
-        closeLoading(context);
+        UIService.closeLoading();
         setState((){
           tokenData = jwt;
           context.setLocale(Locale(tokenData!['language'].toLowerCase()));
@@ -110,7 +112,7 @@ class _AutoLoginPageState extends State<AutoLoginPage> {
         });
       }
     } catch(e){
-      closeLoading(context);
+      UIService.closeLoading();
       debugPrint(e.toString());
       U.showDebugToast(e.toString());
       getTokenData(n: n + 1);
@@ -130,8 +132,9 @@ class _AutoLoginPageState extends State<AutoLoginPage> {
     try {
       // U.clearAccessCode();
       U.clearPreferences().then((value) {
-        context.router.removeLast();
-        context.navigateToPath('/qr?new=true');
+        UIService.navigateNamed('/qr?new=true');
+        // context.router.removeLast();
+        // context.navigateToPath('/qr?new=true');
       });
     } catch(e) {
       debugPrint(e.toString());
@@ -273,16 +276,16 @@ class _AutoLoginPageState extends State<AutoLoginPage> {
           var data = {'oldPassword': dData['password'], 'password': newPassword.trim()};
 
           try {
-            var res = await apiAuthProvider.patchData('/api/informants/${tokenData!['userId']}/changePassword', data, context);
+            var res = await apiAuthProvider.patchData('/api/informants/${tokenData!['userId']}/changePassword', data);
             if (res != null) {
               // setState(() => progressMsg = "Initializing...");
-              String password = tokenData!['related'] && tokenData!['tenantCode'] != null && tokenData!['tenantCode'] != '' ? tokenData!['tenantCode'] + ' ' + data['password'] : data['password'];
+              String password = tokenData!['related'] && tokenData!['tenantCode'] != null && tokenData!['tenantCode'] != '' ? tokenData!['tenantCode'] + ' ${data['password']}' : data['password'];
 
               LoginBody loginBody = LoginBody(dData['username']!, password, 'password');
               Token token = await apiAuthRepository.postLoginUser(loginBody);
               if (token.error != null) {
                 setState(() => loading = false);
-                showError(context, token.error);
+                UIService.showError(token.error.toString());
               } else {
                 setState(() => progressMsg = "redirecting".tr());
                 await U.setChangedPassword(true);
@@ -295,8 +298,9 @@ class _AutoLoginPageState extends State<AutoLoginPage> {
                 await sharedPreferencesManager.putInt(SharedPreferencesManager.keyCountRefreshToken, 0);
                 U.setHidePayload(true);
                 var pid = U.getAccessCode();
-                context.router.removeLast();
-                context.navigateToPath("/app/$pid/menu");
+                UIService.navigateNamed("/app/$pid/menu");
+                // context.router.removeLast();
+                // context.navigateToPath("/app/$pid/menu");
               }
             }
             else{
@@ -308,11 +312,11 @@ class _AutoLoginPageState extends State<AutoLoginPage> {
           }
         }
         else{
-          showError(context, 'checkNewPass'.tr());
+          UIService.showError('checkNewPass'.tr());
         }
       }
       else{
-        showError(context, 'cannotEmpty'.tr());
+        UIService.showError('cannotEmpty'.tr());
       }
     }
   }

+ 4 - 2
lib/src/layouts/components/camera.dart

@@ -1,5 +1,6 @@
 import 'package:camera/camera.dart';
 import 'package:flutter/material.dart';
+import 'package:telnow_mobile_new/src/utils/ui_service.dart';
 
 class OpenCamera extends StatefulWidget {
   final List<CameraDescription>? cameras;
@@ -35,9 +36,10 @@ class _OpenCameraState extends State<OpenCamera> {
     try {
       await _cameraController.setFlashMode(FlashMode.off);
       XFile pickedFile = await _cameraController.takePicture();
-      Navigator.of(context).pop(pickedFile);
+      UIService.navigatorKey.currentState?.pop(pickedFile);
+      // Navigator.of(context).pop(pickedFile);
     } on CameraException catch (e) {
-      debugPrint('Error occured while taking picture: $e');
+      debugPrint('Error occurred while taking picture: $e');
       return null;
     }
   }

+ 2 - 2
lib/src/layouts/components/error_page.dart

@@ -12,10 +12,10 @@ class ErrorPage extends StatefulWidget {
   const ErrorPage(this.code, this.errMsg, {super.key});
 
   @override
-  _ErrorPageState createState() => _ErrorPageState();
+  ErrorPageState createState() => ErrorPageState();
 }
 
-class _ErrorPageState extends State<ErrorPage> {
+class ErrorPageState extends State<ErrorPage> {
   final ApiAuthProvider _apiAuthProvider = ApiAuthProvider();
   String stringError = '';
   String imageUrl = '';

+ 4 - 4
lib/src/layouts/components/photo_chat.dart

@@ -1,6 +1,4 @@
 import 'dart:convert';
-import 'dart:typed_data';
-
 import 'package:camera/camera.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/foundation.dart';
@@ -12,6 +10,7 @@ import 'package:telnow_mobile_new/src/api/api_auth_provider.dart';
 import 'package:telnow_mobile_new/src/layouts/components/camera.dart';
 import 'package:telnow_mobile_new/src/utils/U.dart';
 import 'package:image/image.dart' as img;
+import 'package:telnow_mobile_new/src/utils/ui_service.dart';
 
 class PhotoChat extends StatefulWidget {
   final Map<String, dynamic> data;
@@ -33,7 +32,7 @@ class PhotoChatState extends State<PhotoChat> {
   Future getImage() async {
     XFile? pickedFile;
     if(widget.media == ImageSource.camera){
-      await availableCameras().then((camera) => Navigator.push(context, PageTransition(type: PageTransitionType.rightToLeft, child: OpenCamera(cameras: camera))).then((value) async{
+      await availableCameras().then((camera) => Navigator.push(UIService.navigatorKey.currentContext!, PageTransition(type: PageTransitionType.rightToLeft, child: OpenCamera(cameras: camera))).then((value) async{
         if(value!=null){
           pickedFile = value;
         }
@@ -52,7 +51,8 @@ class PhotoChatState extends State<PhotoChat> {
       var compressed = img.encodeJpg(images, quality: 60);
       setState(() => image = compressed);
     } else {
-      Navigator.of(context).pop(null);
+      UIService.navigatorKey.currentState?.pop(null);
+      // Navigator.of(context).pop(null);
     }
   }
 

+ 1 - 1
lib/src/layouts/components/template.dart

@@ -822,7 +822,7 @@ showLoading(BuildContext context, {String? text, String? lottie}){
     barrierColor: lottie!=null?Colors.white:null,
     builder: (BuildContext context) {
       return WillPopScope(
-        onWillPop: ()=>Future.value(false),
+        onWillPop: () => Future.value(false),
         child: Center(
           child: Column(
             mainAxisSize: MainAxisSize.min,

+ 41 - 36
lib/src/layouts/functions/account.dart

@@ -1,5 +1,4 @@
 import 'package:auto_route/auto_route.dart';
-import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:provider/provider.dart';
 import 'package:telnow_mobile_new/main.dart';
@@ -10,6 +9,7 @@ import 'package:telnow_mobile_new/src/storage/sharedpreferences/shared_preferenc
 import 'package:telnow_mobile_new/src/utils/C.dart';
 import 'package:telnow_mobile_new/src/utils/U.dart';
 import 'package:telnow_mobile_new/src/utils/provider.dart';
+import 'package:telnow_mobile_new/src/utils/ui_service.dart';
 
 class AccountFunction{
   final ApiAuthProvider apiAuthProvider = ApiAuthProvider();
@@ -18,18 +18,19 @@ class AccountFunction{
   final SharedPreferencesManager _sharedPreferencesManager = SharedPreferencesManager();
 
   getUser(BuildContext context) async {
+    final userModule = Provider.of<UserModule>(context, listen: false);
     var res = await token.getUserData(context);
     if (res != null) {
       var ver = await apiAuthProvider.getDataNoAuth('/api/license');
-      Provider.of<UserModule>(context, listen: false).setSerialNum(ver['serialNumber']);
-      Provider.of<UserModule>(context, listen: false).setList(res);
+      userModule.setSerialNum(ver['serialNumber']);
+      userModule.setList(res);
     } else {
-      Provider.of<UserModule>(context, listen: false).setResetData(true);
+      userModule.setResetData(true);
     }
   }
 
-  switchLang(BuildContext context, code, user) async {
-    showLoading(context);
+  switchLang(code, user) async {
+    UIService.showLoading();
     var locale = 'id';
     if(code is int){
       var vl = U.retValidLang();
@@ -45,24 +46,24 @@ class AccountFunction{
       } else {
         p = {'userId': user['userId'], 'language': code.toUpperCase()};
       }
-      var res = await apiAuthProvider.patchData('/api/informants/' + user['id'].toString(), p, context);
+      var res = await apiAuthProvider.patchData('/api/informants/${user['id']}', p);
       if (res != null) {
-        closeLoading(context);
-        context.setLocale(Locale(locale));
-        notification.startNotification(context, code: code);
-        // Navigator.of(context).pop();
+        UIService.closeLoading();
+        UIService.setLocale(Locale(locale));
+        // context.setLocale(Locale(locale));
+        notification.startNotification(code: code);
       } else {
-        closeLoading(context);
+        UIService.closeLoading();
       }
     }catch(e){
-      closeLoading(context);
+      UIService.closeLoading();
     }
   }
 
-  Future<bool> setDndStatus(BuildContext context, bool dnd)async{
-    var res = await apiAuthProvider.patchData('/api/informants/${Provider.of<UserModule>(context, listen: false).user()['id']}/setDnd', null, context, params: {'dnd': '${!dnd}'});
+  Future<bool> setDndStatus(String id, bool dnd)async{
+    var res = await apiAuthProvider.patchData('/api/informants/$id/setDnd', null, params: {'dnd': '${!dnd}'});
     if (res != null) {
-      Provider.of<UserModule>(context, listen: false).setDndStatus(dnd);
+      // Provider.of<UserModule>(context, listen: false).setDndStatus(dnd);
       return true;
     }
     return false;
@@ -72,33 +73,37 @@ class AccountFunction{
     showLoading(context, text: '');
     String pid = U.getPidFromUrl(context.router.currentUrl);
 
+    void loggingOut(){
+      Navigator.of(context).pop();
+      UIService.closeLoading();
+      token.logout();
+      context.navigateToPath("/app/$pid/login");
+    }
+
     try {
-      var tkn = await _sharedPreferencesManager.getString(SharedPreferencesManager.keyFcmToken);
-      // var tkn = await U.getFcmToken();
-      if (tkn == null) {
-        Navigator.of(context).pop();
-        closeLoading(context);
-        token.logout();
-        // context.router.removeLast();
-        context.navigateToPath("/app/$pid/login");
-      } else {
+      var tkn = _sharedPreferencesManager.getString(SharedPreferencesManager.keyFcmToken);
+
+      if (tkn == null)
+      {
+        loggingOut();
+      }
+      else
+      {
         var param = {'token': tkn, 'whiteListToken': false};
         var res = await apiAuthProvider.postData('/api/fcmTokens/remove/', null, param);
-        if (res != null && res['success']) {
-          Navigator.of(context).pop();
-          closeLoading(context);
-          token.logout();
-          // context.router.removeLast();
-          context.navigateToPath("/app/$pid/login");
+
+        if (res != null && res['success'])
+        {
+          loggingOut();
         }
-        else{
-          Future.delayed(const Duration(seconds: 5), () => closeLoading(context));
+        else
+        {
+          Future.delayed(const Duration(seconds: 5), () => UIService.closeLoading());
         }
       }
     } catch(e) {
-      print(e.toString());
-      // context.router.removeLast();
-      context.navigateToPath("/app/$pid/login");
+      debugPrint(e.toString());
+      UIService.navigateNamed("/app/$pid/login");
     }
   }
 }

+ 24 - 18
lib/src/layouts/mobile/app_mobile.dart

@@ -13,6 +13,7 @@ import 'package:telnow_mobile_new/src/injector/injector.dart';
 import 'package:telnow_mobile_new/src/layouts/components/template.dart';
 import 'package:telnow_mobile_new/src/storage/sharedpreferences/shared_preferences_manager.dart';
 import 'package:telnow_mobile_new/src/utils/U.dart';
+import 'package:telnow_mobile_new/src/utils/ui_service.dart';
 
 class MobAppPage extends StatefulWidget {
   final Widget child;
@@ -59,32 +60,37 @@ class _MobAppPageState extends State<MobAppPage>with TickerProviderStateMixin {
 
   checkConnection() async{
     await U.getServerVersion();
-    // getOtherList();
-    SimpleConnectionChecker _simpleConnectionChecker = SimpleConnectionChecker();
-    subscription = _simpleConnectionChecker.onConnectionChange.listen((connected) {
+    final ctx = UIService.context;
+    var langCode = ctx!.locale.toString();
+
+    void initFirebase(){
+      notification.initFirebaseMessaging(context);
+    }
+
+    void checkPendingRequest(){
+      U.checkPendingRequest(context);
+      if(ModalRoute.of(context)?.isCurrent != true) navigateBack(context);
+    }
+
+    SimpleConnectionChecker simpleConnectionChecker = SimpleConnectionChecker();
+    subscription = simpleConnectionChecker.onConnectionChange.listen((connected) {
       U.setInternetStatus(connected);
-      setState(()=>begin = true);
+      setState(() => begin = true);
       if(connected){
-        setState(()=>isConnected = true);
-        notification.initFirebaseMessaging(context);
+        setState(() => isConnected = true);
+        initFirebase();
         var valLang = U.retValidLang();
-        var langCode = context.locale.toString();
-        var code;
+        int? code;
         if(valLang.indexOf(langCode) > 1){
           code = valLang.indexOf(langCode) - 1;
         }
-        notification.startNotification(context, code: code);
-
-        if(U.newServerVersion(1709864293)){
-          U.checkPendingRequest(context);
-        }
-        if(ModalRoute.of(context)?.isCurrent != true) navigateBack(context);
-      }
-      else{
+        notification.startNotification(code: code);
+        checkPendingRequest();
+      } else {
         Future.delayed(Duration(seconds: 4), (){
           if(!U.getInternetStatus()){
-            handlingError(context, 0);
-            setState(()=>isConnected = false);
+            UIService.handlingError(ErrorType.noInternet);
+            setState(() => isConnected = false);
           }
         });
       }

+ 27 - 25
lib/src/layouts/mobile/menu_account.dart

@@ -12,6 +12,7 @@ import 'package:telnow_mobile_new/src/layouts/components/template.dart';
 import 'package:telnow_mobile_new/src/utils/U.dart';
 import 'package:telnow_mobile_new/src/utils/provider.dart';
 import 'package:permission_handler/permission_handler.dart';
+import 'package:telnow_mobile_new/src/utils/ui_service.dart';
 
 import '../../utils/C.dart';
 
@@ -24,7 +25,7 @@ class MobAccountPage extends StatefulWidget {
 
 class _MobAccountPageState extends State<MobAccountPage> {
   final AccountFunction accFunc = AccountFunction();
-  
+
   bool isDeniedNotifPermission = false;
   bool serDis = false;
   bool dnd = false;
@@ -71,6 +72,7 @@ class _MobAccountPageState extends State<MobAccountPage> {
 
   @override
   Widget build(BuildContext context) {
+    final UserModule userModule = Provider.of<UserModule>(context);
     codeOflang = {
       "id": 'bahasa'.tr(),
       "en": 'english'.tr(),
@@ -83,7 +85,7 @@ class _MobAccountPageState extends State<MobAccountPage> {
       "hi": 'hindi'.tr(),
       "nl": 'dutch'.tr()
     };
-    return Provider.of<UserModule>(context).user().isNotEmpty ? Scaffold(
+    return userModule.user().isNotEmpty ? Scaffold(
       backgroundColor: backgroundColor,
       appBar: AppBar(
         elevation: 0,
@@ -110,10 +112,10 @@ class _MobAccountPageState extends State<MobAccountPage> {
                           CircleAvatar(
                             backgroundColor: primaryColor,
                             radius: 25,
-                            child: Text(Provider.of<UserModule>(context).user()['name'][0].toString().toUpperCase(), style: TextStyle(color: Colors.white)),
+                            child: Text(userModule.user()['name'][0].toString().toUpperCase(), style: TextStyle(color: Colors.white)),
                           ),
                           SizedBox(width: 16),
-                          Expanded(child: Text(Provider.of<UserModule>(context).user()['name'], style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500, color: textColor), maxLines: 2, overflow: TextOverflow.ellipsis))
+                          Expanded(child: Text(userModule.user()['name'], style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500, color: textColor), maxLines: 2, overflow: TextOverflow.ellipsis))
                         ],
                       ),
                     ),
@@ -125,16 +127,16 @@ class _MobAccountPageState extends State<MobAccountPage> {
                         children: [
                           Text('info_label'.tr(), style: TextStyle(color: textColor, fontSize: 16, fontWeight: FontWeight.w500)),
                           SizedBox(height: 20),
-                          textHorizontal('userId'.tr(), Provider.of<UserModule>(context).user()['relatedTo'] ?? Provider.of<UserModule>(context).user()['userId'], size: 16, opacity: 0.75),
+                          textHorizontal('userId'.tr(), userModule.user()['relatedTo'] ?? userModule.user()['userId'], size: 16, opacity: 0.75),
                           SizedBox(height: 12),
-                          textHorizontal('location'.tr(), Provider.of<UserModule>(context).user()['location'] ?? '-', size: 16, opacity: 0.75),
+                          textHorizontal('location'.tr(), userModule.user()['location'] ?? '-', size: 16, opacity: 0.75),
                           SizedBox(height: 12),
-                          textHorizontal('servantGroup'.tr(), Provider.of<UserModule>(context).user()['requestTypeListDescriptionMobile'] != null ? Provider.of<UserModule>(context).user()['requestTypeListDescriptionMobile'].toLowerCase() == 'semua' ? 'all'.tr() : Provider.of<UserModule>(context).user()['requestTypeListDescriptionMobile'] : '-', size: 16, opacity: 0.75),
+                          textHorizontal('servantGroup'.tr(), userModule.user()['requestTypeListDescriptionMobile'] != null ? userModule.user()['requestTypeListDescriptionMobile'].toLowerCase() == 'semua' ? 'all'.tr() : userModule.user()['requestTypeListDescriptionMobile'] : '-', size: 16, opacity: 0.75),
                         ],
                       ),
                     ),
-                    Provider.of<UserModule>(context).houseKeeping()?separator():Container(),
-                    Provider.of<UserModule>(context).houseKeeping()?Container(
+                    userModule.houseKeeping()?separator():Container(),
+                    userModule.houseKeeping()?Container(
                       padding: EdgeInsets.all(16),
                       child: Column(
                         crossAxisAlignment: CrossAxisAlignment.start,
@@ -147,23 +149,23 @@ class _MobAccountPageState extends State<MobAccountPage> {
                               Text(dnd?'active_dnd'.tr():'inactive_dnd'.tr(), style: TextStyle(color: textColor, fontSize: 14)),
                               SizedBox(width: 5),
                               GestureDetector(
-                                onTap: Provider.of<UserModule>(context).user()['checkedIn']?(){
+                                onTap: userModule.user()['checkedIn']?(){
                                   dialogConfirm(context: context, title: 'set_dnd_status'.tr(), text: dnd?'msg_change_inactive'.tr():'msg_change_active'.tr(), actionYes: ()async{
-                                    bool res = await accFunc.setDndStatus(context, dnd);
+                                    bool res = await accFunc.setDndStatus(userModule.user()['id'], dnd);
                                     if(res){
                                       setState(() => dnd = !dnd);
                                     }
                                   });
                                 }:null,
                                 child: Container(
-                                  decoration: BoxDecoration(border: Border.all(color: Provider.of<UserModule>(context).user()['checkedIn']?primaryColor:Colors.black38, width: 1.5), borderRadius: BorderRadius.all(Radius.circular(50))),
+                                  decoration: BoxDecoration(border: Border.all(color: userModule.user()['checkedIn']?primaryColor:Colors.black38, width: 1.5), borderRadius: BorderRadius.all(Radius.circular(50))),
                                   child: Row(
                                     children: [
                                       !dnd?Container(
-                                        width: 20, height: 20, decoration: BoxDecoration(color: Provider.of<UserModule>(context).user()['checkedIn']?primaryColor:Colors.black38, borderRadius: BorderRadius.all(Radius.circular(20))),
+                                        width: 20, height: 20, decoration: BoxDecoration(color: userModule.user()['checkedIn']?primaryColor:Colors.black38, borderRadius: BorderRadius.all(Radius.circular(20))),
                                       ):SizedBox(width: 20, height: 20),
                                       dnd?Container(
-                                        width: 20, height: 20, decoration: BoxDecoration(color: Provider.of<UserModule>(context).user()['checkedIn']?primaryColor:Colors.black38, borderRadius: BorderRadius.all(Radius.circular(20))),
+                                        width: 20, height: 20, decoration: BoxDecoration(color: userModule.user()['checkedIn']?primaryColor:Colors.black38, borderRadius: BorderRadius.all(Radius.circular(20))),
                                       ):SizedBox(width: 20, height: 20),
                                     ],
                                   ),
@@ -174,8 +176,8 @@ class _MobAccountPageState extends State<MobAccountPage> {
                         ],
                       ),
                     ):Container(),
-                    !Provider.of<UserModule>(context).user()['_profile']['isRoom']?separator():Container(),
-                    !Provider.of<UserModule>(context).user()['_profile']['isRoom']?Container(
+                    !userModule.user()['_profile']['isRoom']?separator():Container(),
+                    !userModule.user()['_profile']['isRoom']?Container(
                       padding: EdgeInsets.all(16),
                       child: Column(
                         crossAxisAlignment: CrossAxisAlignment.start,
@@ -301,9 +303,9 @@ class _MobAccountPageState extends State<MobAccountPage> {
                                 ],
                               ),
                             ),
-                            onTap: ()=>Navigator.push(context, PageTransition(type: PageTransitionType.rightToLeft, child: MobPasswordPage(user: Provider.of<UserModule>(context, listen: false).user()))).then((value) {
-                              value??false;
-                              if (value) showSuccess(context, 'messagePassChanged'.tr());
+                            onTap: ()=> Navigator.push(context, PageTransition(type: PageTransitionType.rightToLeft, child: MobPasswordPage(user: Provider.of<UserModule>(context, listen: false).user()))).then((value) {
+                              value ?? false;
+                              if (value) UIService.showSuccess('messagePassChanged'.tr());
                             }),
                           ),
                           divider(),
@@ -427,7 +429,7 @@ class _MobAccountPageState extends State<MobAccountPage> {
           )
         ],
       ),
-    ) : Provider.of<UserModule>(context).resetData() ? RefreshPage(() {
+    ) : userModule.resetData() ? RefreshPage(() {
       Provider.of<UserModule>(context, listen: false).setResetData(false);
       accFunc.getUser(context);
     }) : _timeLimit ? showButton(context) : loadingTemplate(() {if(mounted) setState(()=>_timeLimit=true);},);
@@ -466,7 +468,7 @@ class _MobAccountPageState extends State<MobAccountPage> {
             title: Text('bahasa'.tr(), style: TextStyle(color: textColor, fontSize: 14)),
             trailing: Icon(context.locale.toString()=='id'?Icons.radio_button_checked:Icons.radio_button_off, color: primaryColor, size: 18),
             onTap: context.locale.toString() != 'id' ? () async {
-              accFunc.switchLang(context, 'id', user);
+              accFunc.switchLang('id', user);
               Navigator.of(context).pop();
             } : null,
           ),
@@ -474,7 +476,7 @@ class _MobAccountPageState extends State<MobAccountPage> {
             title: Text('english'.tr(), style: TextStyle(color: textColor, fontSize: 14)),
             trailing: Icon(context.locale.toString()=='en'?Icons.radio_button_checked:Icons.radio_button_off, color: primaryColor, size: 18),
             onTap: context.locale.toString() != 'en' ? () async {
-              accFunc.switchLang(context, 'en', user);
+              accFunc.switchLang('en', user);
               Navigator.of(context).pop();
             } : null,
           ),
@@ -483,7 +485,7 @@ class _MobAccountPageState extends State<MobAccountPage> {
             title: Text(codeOflang[lang[2]], style: TextStyle(color: textColor, fontSize: 14)),
             trailing: Icon(context.locale.toString()==lang[2]?Icons.radio_button_checked:Icons.radio_button_off, color: primaryColor, size: 18),
             onTap: context.locale.toString() != lang[2] ? () async {
-              accFunc.switchLang(context, 1, user);
+              accFunc.switchLang(1, user);
               Navigator.of(context).pop();
             } : null,
           ) : Container(),
@@ -491,7 +493,7 @@ class _MobAccountPageState extends State<MobAccountPage> {
             title: Text(codeOflang[lang[3]], style: TextStyle(color: textColor, fontSize: 14)),
             trailing: Icon(context.locale.toString()==lang[3]?Icons.radio_button_checked:Icons.radio_button_off, color: primaryColor, size: 18),
             onTap: context.locale.toString() != lang[3] ? () async {
-              accFunc.switchLang(context, 2, user);
+              accFunc.switchLang(2, user);
               Navigator.of(context).pop();
             } : null,
           ) : Container(),
@@ -499,7 +501,7 @@ class _MobAccountPageState extends State<MobAccountPage> {
             title: Text(codeOflang[lang[4]], style: TextStyle(color: textColor, fontSize: 14)),
             trailing: Icon(context.locale.toString()==lang[4]?Icons.radio_button_checked:Icons.radio_button_off, color: primaryColor, size: 18),
             onTap: context.locale.toString() != lang[4] ? () async {
-              accFunc.switchLang(context, 3, user);
+              accFunc.switchLang(3, user);
               Navigator.of(context).pop();
             } : null,
           ) : Container(),

+ 1 - 1
lib/src/layouts/mobile/message_chat.dart

@@ -59,7 +59,7 @@ class _MobMessageChatPageState extends State<MobMessageChatPage> {
 
   setReadStatus() async {
     if (!widget.askBroadcast) {
-      await apiAuthProvider.patchData('/api/messages/' + widget.messageId, {'readStatus': 'READ'}, context);
+      await apiAuthProvider.patchData('/api/messages/' + widget.messageId, {'readStatus': 'READ'});
     }
   }
 

+ 1 - 1
lib/src/layouts/mobile/password.dart

@@ -88,7 +88,7 @@ class _MobPasswordPageState extends State<MobPasswordPage> {
                       'password':controllerNew.trim()
                     };
             
-                    var res = await apiAuthProvider.patchData('/api/informants/'+widget.user['id'].toString()+'/changePassword', data, context);
+                    var res = await apiAuthProvider.patchData('/api/informants/'+widget.user['id'].toString()+'/changePassword', data);
                     if(res != null){
                       String username = widget.user['_isRelated']?widget.user['relatedTo']:widget.user['userId'];
                       String? password = widget.user['_isRelated'] && widget.user['tenantCode']!=null && widget.user['tenantCode']!=''?widget.user['tenantCode']+' '+data['password']:data['password'];

+ 205 - 206
lib/src/layouts/web/menu_account.dart

@@ -12,6 +12,7 @@ import 'package:telnow_mobile_new/src/layouts/web/password.dart';
 import 'package:telnow_mobile_new/src/utils/U.dart';
 import 'package:telnow_mobile_new/src/utils/provider.dart';
 import 'package:permission_handler/permission_handler.dart';
+import 'package:telnow_mobile_new/src/utils/ui_service.dart';
 
 import '../../utils/C.dart';
 
@@ -62,7 +63,6 @@ class _WebAccountPageState extends State<WebAccountPage> {
       lang = license['languages'] != null ? license['languages'].split(',') : [];
     }
     setState(() {
-      dnd = Provider.of<UserModule>(context, listen: false).dndStatus();
       serDis = U.servantDisplay();
       autoTranslate = U.autoTranslate();
     });
@@ -70,6 +70,9 @@ class _WebAccountPageState extends State<WebAccountPage> {
 
   @override
   Widget build(BuildContext context) {
+    final UserModule userModule = Provider.of<UserModule>(context);
+    dnd = userModule.dndStatus();
+
     codeOflang = {
       "id": 'bahasa'.tr(),
       "en": 'english'.tr(),
@@ -82,7 +85,7 @@ class _WebAccountPageState extends State<WebAccountPage> {
       "hi": 'hindi'.tr(),
       "nl": 'dutch'.tr()
     };
-    return Provider.of<UserModule>(context).user().isNotEmpty ? Scaffold(
+    return userModule.user().isNotEmpty ? Scaffold(
       backgroundColor: backgroundColor,
       appBar: PreferredSize(preferredSize: Size.fromHeight(0), child: AppBar(elevation: 0, backgroundColor: primaryColor)),
       body: Column(
@@ -124,12 +127,12 @@ class _WebAccountPageState extends State<WebAccountPage> {
                                 child: Row(
                                   children: [
                                     CircleAvatar(
-                                      child: Text(Provider.of<UserModule>(context).user()['name'][0].toString().toUpperCase(), style: TextStyle(color: Colors.white)),
                                       backgroundColor: primaryColor,
                                       radius: 25,
+                                      child: Text(userModule.user()['name'][0].toString().toUpperCase(), style: TextStyle(color: Colors.white)),
                                     ),
                                     SizedBox(width: 16),
-                                    Expanded(child: Text(Provider.of<UserModule>(context).user()['name'], style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500, color: textColor), maxLines: 2, overflow: TextOverflow.ellipsis))
+                                    Expanded(child: Text(userModule.user()['name'], style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500, color: textColor), maxLines: 2, overflow: TextOverflow.ellipsis))
                                   ],
                                 ),
                               ),
@@ -141,11 +144,11 @@ class _WebAccountPageState extends State<WebAccountPage> {
                                   children: [
                                     Text('info_label'.tr(), style: TextStyle(color: textColor, fontSize: 16, fontWeight: FontWeight.w500)),
                                     SizedBox(height: 20),
-                                    textHorizontal('userId'.tr(), Provider.of<UserModule>(context).user()['relatedTo'] != null ? Provider.of<UserModule>(context).user()['relatedTo'] : Provider.of<UserModule>(context).user()['userId'], size: 16, opacity: 0.75),
+                                    textHorizontal('userId'.tr(), userModule.user()['relatedTo'] ?? userModule.user()['userId'], size: 16, opacity: 0.75),
                                     SizedBox(height: 12),
-                                    textHorizontal('location'.tr(), Provider.of<UserModule>(context).user()['location'] != null ? Provider.of<UserModule>(context).user()['location'] : '-', size: 16, opacity: 0.75),
+                                    textHorizontal('location'.tr(), userModule.user()['location'] ?? '-', size: 16, opacity: 0.75),
                                     SizedBox(height: 12),
-                                    textHorizontal('servantGroup'.tr(), Provider.of<UserModule>(context).user()['requestTypeListDescriptionMobile'] != null ? Provider.of<UserModule>(context).user()['requestTypeListDescriptionMobile'].toLowerCase() == 'semua' ? 'all'.tr() : Provider.of<UserModule>(context).user()['requestTypeListDescriptionMobile'] : '-', size: 16, opacity: 0.75),
+                                    textHorizontal('servantGroup'.tr(), userModule.user()['requestTypeListDescriptionMobile'] != null ? userModule.user()['requestTypeListDescriptionMobile'].toLowerCase() == 'semua' ? 'all'.tr() : userModule.user()['requestTypeListDescriptionMobile'] : '-', size: 16, opacity: 0.75),
                                   ],
                                 ),
                               ),
@@ -172,215 +175,213 @@ class _WebAccountPageState extends State<WebAccountPage> {
                       child: Column(
                         crossAxisAlignment: CrossAxisAlignment.start,
                         children: [
-                          Provider.of<UserModule>(context).houseKeeping()?Container(
-                            child: Column(
-                              crossAxisAlignment: CrossAxisAlignment.start,
-                              children: [
-                                Text('doNotDisturb'.tr(), style: TextStyle(color: textColor, fontSize: 16, fontWeight: FontWeight.w500)),
-                                SizedBox(height: 20),
-                                Row(
-                                  children: [
-                                    Expanded(child: Text('set_dnd_status'.tr(), style: TextStyle(color: textColor.withValues(alpha: 0.75), fontSize: 16))),
-                                    Text(dnd?'active_dnd'.tr():'inactive_dnd'.tr(), style: TextStyle(color: textColor, fontSize: 14)),
-                                    SizedBox(width: 5),
-                                    GestureDetector(
-                                      child: Container(
-                                        decoration: BoxDecoration(border: Border.all(color: Provider.of<UserModule>(context).user()['checkedIn']?primaryColor:Colors.black38, width: 1.5), borderRadius: BorderRadius.all(Radius.circular(50))),
-                                        child: Row(
-                                          children: [
-                                            !dnd?Container(
-                                              width: 20, height: 20, decoration: BoxDecoration(color: Provider.of<UserModule>(context).user()['checkedIn']?primaryColor:Colors.black38, borderRadius: BorderRadius.all(Radius.circular(20))),
-                                            ):Container(width: 20, height: 20),
-                                            dnd?Container(
-                                              width: 20, height: 20, decoration: BoxDecoration(color: Provider.of<UserModule>(context).user()['checkedIn']?primaryColor:Colors.black38, borderRadius: BorderRadius.all(Radius.circular(20))),
-                                            ):Container(width: 20, height: 20),
-                                          ],
-                                        ),
-                                      ),
-                                      onTap: Provider.of<UserModule>(context).user()['checkedIn']?(){
-                                        dialogConfirm(context: context, title: 'set_dnd_status'.tr(), text: dnd?'msg_change_inactive'.tr():'msg_change_active'.tr(), actionYes: ()async{
-                                          bool res = await accFunc.setDndStatus(context, dnd);
-                                          if(res){
-                                            setState(() => dnd = !dnd);
-                                          }
+                          if (userModule.houseKeeping()) Column(
+                            crossAxisAlignment: CrossAxisAlignment.start,
+                            children: [
+                              Text('doNotDisturb'.tr(), style: TextStyle(color: textColor, fontSize: 16, fontWeight: FontWeight.w500)),
+                              SizedBox(height: 20),
+                              Row(
+                                children: [
+                                  Expanded(child: Text('set_dnd_status'.tr(), style: TextStyle(color: textColor.withValues(alpha: 0.75), fontSize: 16))),
+                                  Text(dnd?'active_dnd'.tr():'inactive_dnd'.tr(), style: TextStyle(color: textColor, fontSize: 14)),
+                                  SizedBox(width: 5),
+                                  GestureDetector(
+                                    onTap: (){
+                                      if(userModule.user()['checkedIn']){
+                                        dialogConfirm(
+                                          context: context,
+                                          title: 'set_dnd_status'.tr(),
+                                          text: dnd ? 'msg_change_inactive'.tr() : 'msg_change_active'.tr(),
+                                          actionYes: ()async{
+                                            bool res = await accFunc.setDndStatus(userModule.user()['id'], dnd);
+                                            if(res){
+                                              userModule.setDndStatus(!dnd);
+                                            }
                                         });
-                                      }:null,
+                                      }
+                                    },
+                                    child: Container(
+                                      decoration: BoxDecoration(border: Border.all(color: userModule.user()['checkedIn']?primaryColor:Colors.black38, width: 1.5), borderRadius: BorderRadius.all(Radius.circular(50))),
+                                      child: Row(
+                                        children: [
+                                          !dnd?Container(
+                                            width: 20, height: 20, decoration: BoxDecoration(color: userModule.user()['checkedIn']?primaryColor:Colors.black38, borderRadius: BorderRadius.all(Radius.circular(20))),
+                                          ):SizedBox(width: 20, height: 20),
+                                          dnd?Container(
+                                            width: 20, height: 20, decoration: BoxDecoration(color: userModule.user()['checkedIn']?primaryColor:Colors.black38, borderRadius: BorderRadius.all(Radius.circular(20))),
+                                          ):SizedBox(width: 20, height: 20),
+                                        ],
+                                      ),
                                     ),
-                                  ],
-                                )
-                              ],
-                            ),
-                          ):Container(),
-                          Provider.of<UserModule>(context).houseKeeping()?Padding(padding: EdgeInsets.symmetric(vertical: 16), child: separator()):Container(),
-
-                          !Provider.of<UserModule>(context).user()['_profile']['isRoom']?Container(
-                            child: Column(
-                              crossAxisAlignment: CrossAxisAlignment.start,
-                              children: [
-                                Text('display_menu'.tr(), style: TextStyle(color: textColor, fontSize: 16, fontWeight: FontWeight.w500)),
-                                SizedBox(height: 20),
-                                Row(
+                                  ),
+                                ],
+                              )
+                            ],
+                          ),
+                          if(userModule.houseKeeping()) Padding(padding: EdgeInsets.symmetric(vertical: 16), child: separator()),
+                          if(!userModule.user()['_profile']['isRoom']) Column(
+                            crossAxisAlignment: CrossAxisAlignment.start,
+                            children: [
+                              Text('display_menu'.tr(), style: TextStyle(color: textColor, fontSize: 16, fontWeight: FontWeight.w500)),
+                              SizedBox(height: 20),
+                              Row(
+                                children: [
+                                  Expanded(child: Text(serDis?'ser_group'.tr():'req_group'.tr(), style: TextStyle(color: textColor.withValues(alpha: 0.75), fontSize: 16))),
+                                  SizedBox(width: 5),
+                                  GestureDetector(
+                                    child: Container(
+                                      decoration: BoxDecoration(border: Border.all(color: primaryColor, width: 1.5), borderRadius: BorderRadius.all(Radius.circular(50))),
+                                      child: Row(
+                                        children: [
+                                          !serDis?Container(
+                                            width: 20, height: 20, decoration: BoxDecoration(color: primaryColor, borderRadius: BorderRadius.all(Radius.circular(20))),
+                                          ):SizedBox(width: 20, height: 20),
+                                          serDis?Container(
+                                            width: 20, height: 20, decoration: BoxDecoration(color: primaryColor, borderRadius: BorderRadius.all(Radius.circular(20))),
+                                          ):SizedBox(width: 20, height: 20),
+                                        ],
+                                      ),
+                                    ),
+                                    onTap: (){
+                                      setState(() {
+                                        if(serDis){
+                                          U.setServantDisplay(false);
+                                          serDis = false;
+                                        }
+                                        else{
+                                          U.setServantDisplay(true);
+                                          serDis = true;
+                                        }
+                                      });
+                                    },
+                                  ),
+                                ],
+                              )
+                            ],
+                          ),
+                          if(!userModule.user()['_profile']['isRoom']) Padding(padding: EdgeInsets.symmetric(vertical: 16), child: separator()),
+                          Column(
+                            crossAxisAlignment: CrossAxisAlignment.start,
+                            children: [
+                              Text('setting'.tr(), style: TextStyle(color: textColor, fontSize: 16, fontWeight: FontWeight.w500)),
+                              SizedBox(height: 6),
+                              GestureDetector(
+                                child: Container(
+                                  color: Colors.white,
+                                  padding: EdgeInsets.symmetric(vertical: 16),
+                                  child: Row(
+                                    children: [
+                                      U.iconsax('bold/global', color: textColor.withValues(alpha: 0.75)),
+                                      SizedBox(width: 16),
+                                      Expanded(child: Text('language'.tr(), style: TextStyle(color: textColor.withValues(alpha: 0.75), fontSize: 16), overflow: TextOverflow.ellipsis)),
+                                      Text(codeOflang[context.locale.toString()]!, style: TextStyle(color: textColor)),
+                                      SizedBox(width: 12),
+                                      U.iconsax('arrow-right-3', size: 16, color: textColor.withValues(alpha: 0.75)),
+                                    ],
+                                  ),
+                                ),
+                                onTap: () => changeLang(context, Provider.of<UserModule>(context, listen: false).user()),
+                              ),
+                              divider(),
+                              Container(
+                                color: Colors.white,
+                                padding: EdgeInsets.symmetric(vertical: 16),
+                                child: Row(
                                   children: [
-                                    Expanded(child: Text(serDis?'ser_group'.tr():'req_group'.tr(), style: TextStyle(color: textColor.withValues(alpha: 0.75), fontSize: 16))),
+                                    Icon(Icons.g_translate_rounded, color: textColor.withValues(alpha: 0.75)),
+                                    SizedBox(width: 16),
+                                    Expanded(child: Text('auto_translate'.tr(), style: TextStyle(color: textColor.withValues(alpha: 0.75), fontSize: 16), overflow: TextOverflow.ellipsis)),
+                                    Text(autoTranslate?'ON':'OFF', style: TextStyle(color: textColor)),
                                     SizedBox(width: 5),
                                     GestureDetector(
                                       child: Container(
-                                        decoration: BoxDecoration(border: Border.all(color: primaryColor, width: 1.5), borderRadius: BorderRadius.all(Radius.circular(50))),
+                                        decoration: BoxDecoration(border: Border.all(color: autoTranslate?primaryColor:Colors.black38, width: 1.5), borderRadius: BorderRadius.all(Radius.circular(50))),
                                         child: Row(
                                           children: [
-                                            !serDis?Container(
-                                              width: 20, height: 20, decoration: BoxDecoration(color: primaryColor, borderRadius: BorderRadius.all(Radius.circular(20))),
-                                            ):Container(width: 20, height: 20),
-                                            serDis?Container(
+                                            !autoTranslate?Container(
+                                              width: 20, height: 20, decoration: BoxDecoration(color: Colors.black38, borderRadius: BorderRadius.all(Radius.circular(20))),
+                                            ):SizedBox(width: 20, height: 20),
+                                            autoTranslate?Container(
                                               width: 20, height: 20, decoration: BoxDecoration(color: primaryColor, borderRadius: BorderRadius.all(Radius.circular(20))),
-                                            ):Container(width: 20, height: 20),
+                                            ):SizedBox(width: 20, height: 20),
                                           ],
                                         ),
                                       ),
                                       onTap: (){
                                         setState(() {
-                                          if(serDis){
-                                            U.setServantDisplay(false);
-                                            serDis = false;
+                                          if(autoTranslate){
+                                            U.setAutoTranslate(false);
+                                            autoTranslate = false;
                                           }
                                           else{
-                                            U.setServantDisplay(true);
-                                            serDis = true;
+                                            U.setAutoTranslate(true);
+                                            autoTranslate = true;
                                           }
                                         });
                                       },
                                     ),
                                   ],
-                                )
-                              ],
-                            ),
-                          ):Container(),
-                          !Provider.of<UserModule>(context).user()['_profile']['isRoom']?Padding(padding: EdgeInsets.symmetric(vertical: 16), child: separator()):Container(),
-
-                          Container(
-                            child: Column(
-                              crossAxisAlignment: CrossAxisAlignment.start,
-                              children: [
-                                Text('setting'.tr(), style: TextStyle(color: textColor, fontSize: 16, fontWeight: FontWeight.w500)),
-                                SizedBox(height: 6),
-                                GestureDetector(
-                                  child: Container(
-                                    color: Colors.white,
-                                    padding: EdgeInsets.symmetric(vertical: 16),
-                                    child: Row(
-                                      children: [
-                                        U.iconsax('bold/global', color: textColor.withValues(alpha: 0.75)),
-                                        SizedBox(width: 16),
-                                        Expanded(child: Text('language'.tr(), style: TextStyle(color: textColor.withValues(alpha: 0.75), fontSize: 16), overflow: TextOverflow.ellipsis)),
-                                        Text(codeOflang[context.locale.toString()]!, style: TextStyle(color: textColor)),
-                                        SizedBox(width: 12),
-                                        U.iconsax('arrow-right-3', size: 16, color: textColor.withValues(alpha: 0.75)),
-                                      ],
-                                    ),
-                                  ),
-                                  onTap: () => changeLang(context, Provider.of<UserModule>(context, listen: false).user()),
                                 ),
-                                divider(),
-                                Container(
+                              ),
+                              divider(),
+                              GestureDetector(
+                                child: Container(
                                   color: Colors.white,
                                   padding: EdgeInsets.symmetric(vertical: 16),
                                   child: Row(
                                     children: [
-                                      Icon(Icons.g_translate_rounded, color: textColor.withValues(alpha: 0.75)),
+                                      U.iconsax('bold/key', color: textColor.withValues(alpha: 0.75)),
                                       SizedBox(width: 16),
-                                      Expanded(child: Text('auto_translate'.tr(), style: TextStyle(color: textColor.withValues(alpha: 0.75), fontSize: 16), overflow: TextOverflow.ellipsis)),
-                                      Text(autoTranslate?'ON':'OFF', style: TextStyle(color: textColor)),
-                                      SizedBox(width: 5),
-                                      GestureDetector(
-                                        child: Container(
-                                          decoration: BoxDecoration(border: Border.all(color: autoTranslate?primaryColor:Colors.black38, width: 1.5), borderRadius: BorderRadius.all(Radius.circular(50))),
-                                          child: Row(
-                                            children: [
-                                              !autoTranslate?Container(
-                                                width: 20, height: 20, decoration: BoxDecoration(color: Colors.black38, borderRadius: BorderRadius.all(Radius.circular(20))),
-                                              ):Container(width: 20, height: 20),
-                                              autoTranslate?Container(
-                                                width: 20, height: 20, decoration: BoxDecoration(color: primaryColor, borderRadius: BorderRadius.all(Radius.circular(20))),
-                                              ):Container(width: 20, height: 20),
-                                            ],
-                                          ),
-                                        ),
-                                        onTap: (){
-                                          setState(() {
-                                            if(autoTranslate){
-                                              U.setAutoTranslate(false);
-                                              autoTranslate = false;
-                                            }
-                                            else{
-                                              U.setAutoTranslate(true);
-                                              autoTranslate = true;
-                                            }
-                                          });
-                                        },
-                                      ),
+                                      Text('password'.tr(), style: TextStyle(color: textColor.withValues(alpha: 0.75), fontSize: 16)),
+                                      Expanded(child: Text('settingPasswordText'.tr(), style: TextStyle(color: textColor), overflow: TextOverflow.ellipsis, textAlign: TextAlign.end)),
+                                      SizedBox(width: 12),
+                                      U.iconsax('arrow-right-3', size: 16, color: textColor.withValues(alpha: 0.75)),
                                     ],
                                   ),
                                 ),
-                                divider(),
-                                GestureDetector(
-                                  child: Container(
-                                    color: Colors.white,
-                                    padding: EdgeInsets.symmetric(vertical: 16),
-                                    child: Row(
-                                      children: [
-                                        U.iconsax('bold/key', color: textColor.withValues(alpha: 0.75)),
-                                        SizedBox(width: 16),
-                                        Text('password'.tr(), style: TextStyle(color: textColor.withValues(alpha: 0.75), fontSize: 16)),
-                                        Expanded(child: Text('settingPasswordText'.tr(), style: TextStyle(color: textColor), overflow: TextOverflow.ellipsis, textAlign: TextAlign.end)),
-                                        SizedBox(width: 12),
-                                        U.iconsax('arrow-right-3', size: 16, color: textColor.withValues(alpha: 0.75)),
-                                      ],
-                                    ),
-                                  ),
-                                  onTap: ()=>Navigator.push(context, PageTransition(type: PageTransitionType.rightToLeft, child: WebPasswordPage(user: Provider.of<UserModule>(context, listen: false).user()))).then((value) {
-                                    value??false;
-                                    if (value) showSuccess(context, 'messagePassChanged'.tr());
-                                  }),
-                                ),
-                                divider(),
-                                GestureDetector(
-                                  child: Container(
-                                    color: Colors.white,
-                                    padding: EdgeInsets.symmetric(vertical: 16),
-                                    child: Row(
-                                      children: [
-                                        U.iconsax('bold/logout', color: textColor.withValues(alpha: 0.75)),
-                                        SizedBox(width: 16),
-                                        Expanded(child: Text('logout'.tr(), style: TextStyle(color: textColor.withValues(alpha: 0.75), fontSize: 16), overflow: TextOverflow.ellipsis)),
-                                        U.iconsax('arrow-right-3', size: 16, color: textColor.withValues(alpha: 0.75)),
-                                      ],
-                                    ),
+                                onTap: ()=>Navigator.push(context, PageTransition(type: PageTransitionType.rightToLeft, child: WebPasswordPage(user: Provider.of<UserModule>(context, listen: false).user()))).then((value) {
+                                  value??false;
+                                  if (value) UIService.showSuccess('messagePassChanged'.tr());
+                                }),
+                              ),
+                              divider(),
+                              GestureDetector(
+                                child: Container(
+                                  color: Colors.white,
+                                  padding: EdgeInsets.symmetric(vertical: 16),
+                                  child: Row(
+                                    children: [
+                                      U.iconsax('bold/logout', color: textColor.withValues(alpha: 0.75)),
+                                      SizedBox(width: 16),
+                                      Expanded(child: Text('logout'.tr(), style: TextStyle(color: textColor.withValues(alpha: 0.75), fontSize: 16), overflow: TextOverflow.ellipsis)),
+                                      U.iconsax('arrow-right-3', size: 16, color: textColor.withValues(alpha: 0.75)),
+                                    ],
                                   ),
-                                  onTap: (){
-                                    showDialog(
-                                      context: context,
-                                      builder: (BuildContext context) {
-                                        return AlertDialog(
-                                          title: Text("logout".tr()),
-                                          content: Text("textLogout".tr()),
-                                          actions: <Widget>[
-                                            TextButton(
-                                              child: Text("buttonNo".tr()),
-                                              onPressed: () {
-                                                Navigator.of(context).pop();
-                                              },
-                                            ),
-                                            TextButton(
-                                                onPressed: () => accFunc.logoutAction(context),
-                                                child: Text("buttonYes".tr())),
-                                          ],
-                                        );
-                                      },
-                                    );
-                                  },
                                 ),
-                              ],
-                            ),
+                                onTap: (){
+                                  showDialog(
+                                    context: context,
+                                    builder: (BuildContext context) {
+                                      return AlertDialog(
+                                        title: Text("logout".tr()),
+                                        content: Text("textLogout".tr()),
+                                        actions: <Widget>[
+                                          TextButton(
+                                            child: Text("buttonNo".tr()),
+                                            onPressed: () {
+                                              Navigator.of(context).pop();
+                                            },
+                                          ),
+                                          TextButton(
+                                              onPressed: () => accFunc.logoutAction(context),
+                                              child: Text("buttonYes".tr())),
+                                        ],
+                                      );
+                                    },
+                                  );
+                                },
+                              ),
+                            ],
                           ),
                           separator(),
                           GestureDetector(
@@ -399,7 +400,7 @@ class _WebAccountPageState extends State<WebAccountPage> {
                             onTap: (){
                               var size = MediaQuery.of(context).size.height/2;
                               var pid = U.getPidFromUrl(context.router.currentUrl);
-                              var qr_data = 'https://telnow.telmessenger.com/#/app/${pid}%23${U.getBaseUrl()}';
+                              var qrData = 'https://telnow.telmessenger.com/#/app/$pid%23${U.getBaseUrl()}';
                               showDialog(
                                 context: context,
                                 builder: (BuildContext context) {
@@ -413,7 +414,7 @@ class _WebAccountPageState extends State<WebAccountPage> {
                                           width: size,
                                           height: size,
                                           child: QrImageView(
-                                            data: qr_data,
+                                            data: qrData,
                                             version: QrVersions.auto,
                                             gapless: true,
                                           ),
@@ -428,21 +429,19 @@ class _WebAccountPageState extends State<WebAccountPage> {
                             },
                           ),
                           isDeniedNotifPermission ? Padding(padding: EdgeInsets.symmetric(vertical: 16), child: separator()) : Container(),
-                          isDeniedNotifPermission ? Container(
-                            child: GestureDetector(
-                              child: Column(
-                                crossAxisAlignment: CrossAxisAlignment.start,
-                                children: [
-                                  Text("not_allow_permission".tr()),
-                                  SizedBox(height: 8,),
-                                  Text("tap_here".tr(), style: TextStyle(color: Color(0xFF198AF2)),),
-                                ],
-                              ),
-                              onTap: () => AppSettings.openAppSettings(type: AppSettingsType.notification).then((value) async {
-                                // print("after open setting");
-                                // checkPermission(2);
-                              }),
+                          isDeniedNotifPermission ? GestureDetector(
+                            child: Column(
+                              crossAxisAlignment: CrossAxisAlignment.start,
+                              children: [
+                                Text("not_allow_permission".tr()),
+                                SizedBox(height: 8,),
+                                Text("tap_here".tr(), style: TextStyle(color: Color(0xFF198AF2)),),
+                              ],
                             ),
+                            onTap: () => AppSettings.openAppSettings(type: AppSettingsType.notification).then((value) async {
+                              // print("after open setting");
+                              // checkPermission(2);
+                            }),
                           ) : Container(),
                         ],
                       ),
@@ -454,7 +453,7 @@ class _WebAccountPageState extends State<WebAccountPage> {
           )
         ],
       ),
-    ) : Provider.of<UserModule>(context).resetData() ? RefreshPage(() {
+    ) : userModule.resetData() ? RefreshPage(() {
       Provider.of<UserModule>(context, listen: false).setResetData(false);
       accFunc.getUser(context);
     }) : _timeLimit ? showButton(context) : loadingTemplate(() {if(mounted) setState(()=>_timeLimit=true);},);
@@ -495,7 +494,7 @@ class _WebAccountPageState extends State<WebAccountPage> {
             title: Text('bahasa'.tr(), style: TextStyle(color: textColor, fontSize: 14)),
             trailing: Icon(context.locale.toString()=='id'?Icons.radio_button_checked:Icons.radio_button_off, color: primaryColor, size: 18),
             onTap: context.locale.toString() != 'id' ? () async {
-              accFunc.switchLang(context, 'id', user);
+              accFunc.switchLang('id', user);
               Navigator.of(cd).pop();
             } : null,
           ),
@@ -503,7 +502,7 @@ class _WebAccountPageState extends State<WebAccountPage> {
             title: Text('english'.tr(), style: TextStyle(color: textColor, fontSize: 14)),
             trailing: Icon(context.locale.toString()=='en'?Icons.radio_button_checked:Icons.radio_button_off, color: primaryColor, size: 18),
             onTap: context.locale.toString() != 'en' ? () async {
-              accFunc.switchLang(context, 'en', user);
+              accFunc.switchLang('en', user);
               Navigator.of(cd).pop();
             } : null,
           ),
@@ -511,7 +510,7 @@ class _WebAccountPageState extends State<WebAccountPage> {
             title: Text(codeOflang[lang[2]], style: TextStyle(color: textColor, fontSize: 14)),
             trailing: Icon(context.locale.toString()==lang[2]?Icons.radio_button_checked:Icons.radio_button_off, color: primaryColor, size: 18),
             onTap: context.locale.toString() != lang[2] ? () async {
-              accFunc.switchLang(context, 1, user);
+              accFunc.switchLang(1, user);
               Navigator.of(cd).pop();
             } : null,
           ) : Container(),
@@ -519,7 +518,7 @@ class _WebAccountPageState extends State<WebAccountPage> {
             title: Text(codeOflang[lang[3]], style: TextStyle(color: textColor, fontSize: 14)),
             trailing: Icon(context.locale.toString()==lang[3]?Icons.radio_button_checked:Icons.radio_button_off, color: primaryColor, size: 18),
             onTap: context.locale.toString() != lang[3] ? () async {
-              accFunc.switchLang(context, 2, user);
+              accFunc.switchLang(2, user);
               Navigator.of(cd).pop();
             } : null,
           ) : Container(),
@@ -527,7 +526,7 @@ class _WebAccountPageState extends State<WebAccountPage> {
             title: Text(codeOflang[lang[4]], style: TextStyle(color: textColor, fontSize: 14)),
             trailing: Icon(context.locale.toString()==lang[4]?Icons.radio_button_checked:Icons.radio_button_off, color: primaryColor, size: 18),
             onTap: context.locale.toString() != lang[4] ? () async {
-              accFunc.switchLang(context, 3, user);
+              accFunc.switchLang(3, user);
               Navigator.of(cd).pop();
             } : null,
           ) : Container(),

+ 1 - 1
lib/src/layouts/web/message_list.dart

@@ -108,7 +108,7 @@ class _WebMessageListPageState extends State<WebMessageListPage> {
 
       scrollController.addListener(() => scrollListener());
       if (!isMe) {
-        await apiAuthProvider.patchData('/api/messages/' + data['id'].toString(), {'readStatus': 'READ'}, context);
+        await apiAuthProvider.patchData('/api/messages/' + data['id'].toString(), {'readStatus': 'READ'});
       }
 
       getMessage();

+ 2 - 2
lib/src/layouts/web/password.dart

@@ -57,6 +57,7 @@ class _WebPasswordPageState extends State<WebPasswordPage> {
                     alignment: Alignment.topLeft,
                     width: MediaQuery.of(context).size.width/3,
                     padding: EdgeInsets.all(20),
+                    decoration: BoxDecoration(color: Colors.white, border: Border.all(color: textColor.withValues(alpha: 0.15)), borderRadius: BorderRadius.all(Radius.circular(12))),
                     child: Column(
                       crossAxisAlignment: CrossAxisAlignment.start,
                       children: [
@@ -94,7 +95,7 @@ class _WebPasswordPageState extends State<WebPasswordPage> {
                                 'password':controllerNew.trim()
                               };
 
-                              var res = await apiAuthProvider.patchData('/api/informants/'+widget.user['id'].toString()+'/changePassword', data, context);
+                              var res = await apiAuthProvider.patchData('/api/informants/'+widget.user['id'].toString()+'/changePassword', data);
                               if(res != null){
                                 String username = widget.user['_isRelated']?widget.user['relatedTo']:widget.user['userId'];
                                 String? password = widget.user['_isRelated'] && widget.user['tenantCode']!=null && widget.user['tenantCode']!=''?widget.user['tenantCode']+' '+data['password']:data['password'];
@@ -122,7 +123,6 @@ class _WebPasswordPageState extends State<WebPasswordPage> {
                         })
                       ],
                     ),
-                    decoration: BoxDecoration(color: Colors.white, border: Border.all(color: textColor.withValues(alpha: 0.15)), borderRadius: BorderRadius.all(Radius.circular(12))),
                   ),
                   Expanded(child: Container())
                 ],

+ 62 - 0
lib/src/utils/ui_service.dart

@@ -3,6 +3,7 @@ import 'package:another_flushbar/flushbar.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
+import 'package:lottie/lottie.dart';
 import 'package:page_transition/page_transition.dart';
 import 'package:telnow_mobile_new/src/injector/injector.dart';
 import 'package:telnow_mobile_new/src/layouts/auth/qr.dart';
@@ -85,6 +86,24 @@ class UIService {
     }
   }
 
+  static void showSuccess(message) {
+    final ctx = context;
+    if (ctx != null) {
+      Flushbar(
+        message: message,
+        icon: Icon(
+          Icons.info_outline,
+          size: 28.0,
+          color: Colors.green,
+        ),
+        duration: Duration(seconds: 5),
+        flushbarPosition: FlushbarPosition.BOTTOM,
+        margin: EdgeInsets.all(8),
+        borderRadius: BorderRadius.all(Radius.circular(8)),
+      ).show(ctx);
+    }
+  }
+
   static bool get isCurrentRouteInactive {
     final ctx = context;
     final route = ModalRoute.of(ctx ?? navigatorKey.currentState?.context ?? ctx!);
@@ -95,6 +114,49 @@ class UIService {
     navigatorKey.currentState?.maybePop();
   }
 
+  static void setLocale(code) {
+    final ctx = context;
+    if(ctx == null) return;
+    ctx.setLocale(code);
+  }
+
+  static void showLoading({String? text, String? lottie}){
+    final ctx = context;
+    if(ctx == null) return;
+    showDialog(
+      context: ctx,
+      barrierDismissible: false,
+      barrierColor: lottie != null ? Colors.white : null,
+        builder: (BuildContext context) {
+          return WillPopScope(
+            onWillPop: () => Future.value(false),
+            child: Material(
+              type: MaterialType.transparency,
+              child: Center(
+                child: Column(
+                  mainAxisSize: MainAxisSize.min,
+                  children: [
+                    lottie != null
+                        ? Lottie.asset('assets/image/lottie/$lottie', width: 250, height: 250, fit: BoxFit.fill)
+                        : CircularProgressIndicator(color: primaryColor),
+                    SizedBox(height: 5),
+                    Text(
+                      text ?? 'inProcess'.tr(),
+                      style: TextStyle(color: lottie != null ? Colors.black : Colors.white),
+                    ),
+                  ],
+                ),
+              ),
+            ),
+          );
+        }
+    );
+  }
+
+  static void closeLoading(){
+    Navigator.of(navigatorKey.currentContext!, rootNavigator: true).pop();
+  }
+
   static void handlingError(ErrorType type) {
     var data = [
       {