U.dart 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  1. import 'dart:async';
  2. import 'package:easy_localization/easy_localization.dart';
  3. import 'package:firebase_messaging/firebase_messaging.dart';
  4. import 'package:flutter/foundation.dart';
  5. import 'package:flutter/material.dart';
  6. import 'package:flutter_randomcolor/flutter_randomcolor.dart';
  7. import 'package:flutter_svg/svg.dart';
  8. import 'package:jwt_decoder/jwt_decoder.dart';
  9. import 'package:telnow_mobile_new/src/api/api_auth_repository.dart';
  10. import 'package:telnow_mobile_new/src/model/token/token.dart';
  11. import 'dart:convert';
  12. import 'package:flutter_local_notifications/flutter_local_notifications.dart';
  13. import 'package:fluttertoast/fluttertoast.dart';
  14. import 'package:telnow_mobile_new/src/api/api_auth_provider.dart';
  15. import 'package:telnow_mobile_new/src/api/jwt_token.dart';
  16. import 'package:telnow_mobile_new/src/injector/injector.dart';
  17. import 'package:telnow_mobile_new/src/model/refreshtoken/refresh_token_body.dart';
  18. import 'package:telnow_mobile_new/src/layouts/components/template.dart';
  19. import 'package:telnow_mobile_new/src/storage/sharedpreferences/shared_preferences_manager.dart';
  20. import 'package:synchronized/synchronized.dart';
  21. import 'cache_manager.dart';
  22. import 'C.dart';
  23. const Color backgroundColor = Colors.white;
  24. const Color primaryColor = Color(0xff078C84);
  25. const Color secondaryColor = Color(0xffCC6029);
  26. const Color textColor = Color(0xff292D32);
  27. const Color disabledColor = Color(0xff989696);
  28. class U {
  29. static final String passphrase = "telmessenger-key";
  30. static final SharedPreferencesManager _sharedPreferencesManager = locator<SharedPreferencesManager>();
  31. static dynamic _license;
  32. static dynamic _userData;
  33. static String rawPid = '';
  34. static String _url = '';
  35. static bool _hasChangedPassword = true;
  36. static bool _loadAfterRequest = false;
  37. static bool? _connected;
  38. static bool _notifPermission = false;
  39. static bool _notifPermissionDismissed = false;
  40. // static final ApiAuthProvider _apiAuthProvider = ApiAuthProvider();
  41. static final Codec<String, String> stringToBase64Url = utf8.fuse(base64Url);
  42. static final JwtToken token = JwtToken();
  43. static final _lockAuth = Lock();
  44. static int _authLastMs = 0;
  45. static Token? _lastReqToken;
  46. static final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
  47. static const AndroidNotificationChannel channel = AndroidNotificationChannel(
  48. 'notification_channel', // id
  49. 'Normal Notification', // title
  50. description: 'This channel is used for normal notifications.', // description
  51. importance: Importance.high,
  52. enableLights: true,
  53. playSound: true,
  54. sound: RawResourceAndroidNotificationSound('notification_alarm'),
  55. );
  56. // =
  57. // FlutterLocalNotificationsPlugin();
  58. static Future<Token?> _tryRefreshAuth(RefreshTokenBody refreshTokenBody,
  59. {int n = 0}) async {
  60. ApiAuthRepository apiAuthRepository = ApiAuthRepository();
  61. try {
  62. Token token = await apiAuthRepository.postRefreshAuth(refreshTokenBody);
  63. await _sharedPreferencesManager.putString(
  64. SharedPreferencesManager.keyAccessToken, token.accessToken!);
  65. await _sharedPreferencesManager.putString(
  66. SharedPreferencesManager.keyRefreshToken, token.refreshToken!);
  67. return Future.value(token);
  68. } catch (error) {
  69. if (n < 3) {
  70. return _tryRefreshAuth(refreshTokenBody, n: n++);
  71. } else {
  72. await _sharedPreferencesManager.putString(
  73. SharedPreferencesManager.keyAccessToken, '');
  74. await _sharedPreferencesManager.putString(
  75. SharedPreferencesManager.keyRefreshToken, '');
  76. Future.error(error);
  77. }
  78. }
  79. }
  80. static Future waitForRefreshAuth() async {
  81. if(JwtDecoder.isExpired(_sharedPreferencesManager.getString(SharedPreferencesManager.keyAccessToken)!)){
  82. // print("get new token");
  83. String? refreshToken = _sharedPreferencesManager.getString(SharedPreferencesManager.keyRefreshToken)!;
  84. RefreshTokenBody? refreshTokenBody = RefreshTokenBody('refresh_token', refreshToken);
  85. refreshAuth(refreshTokenBody);
  86. } else {
  87. // print(JwtDecoder.getRemainingTime(_sharedPreferencesManager.getString(SharedPreferencesManager.keyAccessToken)!));
  88. }
  89. // return _lockAuth.synchronized(() async {
  90. // print("wait refresh token OK");
  91. // });
  92. }
  93. static Future<Token?> refreshAuth(RefreshTokenBody refreshTokenBody) async {
  94. // print("refresh token");
  95. // return _lockAuth.synchronized(() async { //lock bikin stuck
  96. // print("refresh token start");
  97. var nw = DateTime.now().millisecondsSinceEpoch;
  98. if (_authLastMs == 0 || nw - _authLastMs >= 5000) {
  99. // print("refresh token request");
  100. ApiAuthRepository apiAuthRepository = ApiAuthRepository();
  101. var token = await _tryRefreshAuth(refreshTokenBody);
  102. _authLastMs = DateTime.now().millisecondsSinceEpoch;
  103. _lastReqToken = token;
  104. }
  105. // print("refresh token finish");
  106. return _lastReqToken;
  107. // });
  108. // if (token != null) {
  109. // _authLastMs = DateTime.now().millisecondsSinceEpoch;
  110. // _lastReqToken = token;
  111. // }
  112. // print("refresh token finish");
  113. // return Future.value(_lastReqToken);
  114. }
  115. static Future <String?> getFcmToken() async {
  116. // print("minta fcm nya");
  117. if (_sharedPreferencesManager.getString(SharedPreferencesManager.keyFcmToken) != "" && _sharedPreferencesManager.getString(SharedPreferencesManager.keyFcmToken) != null) {
  118. // print("return shared aja");
  119. return _sharedPreferencesManager.getString(SharedPreferencesManager.keyFcmToken);
  120. } else {
  121. try {
  122. var token = await FirebaseMessaging.instance.getToken();
  123. if (token != null) {
  124. _sharedPreferencesManager.putString(SharedPreferencesManager.keyFcmToken, token);
  125. // print("token from U: $token");
  126. return token;
  127. }
  128. } catch(e) {
  129. print(e.toString());
  130. return null;
  131. }
  132. }
  133. return null;
  134. }
  135. static void clearUserData() {
  136. _userData = null;
  137. }
  138. static void clearLicenseData() {
  139. _license = null;
  140. }
  141. static void setNotifPermission(value) {
  142. _notifPermission = value;
  143. }
  144. static getNotifPermission(){
  145. return _notifPermission;
  146. }
  147. static void setNotifPermissionDismissed(value) {
  148. _notifPermissionDismissed = value;
  149. }
  150. static getNotifPermissionDismissed(){
  151. return _notifPermissionDismissed;
  152. }
  153. static void savePreferences(token) async {
  154. // print('save preferences!');
  155. await _sharedPreferencesManager.putString(SharedPreferencesManager.keyAccessToken, token.accessToken);
  156. await _sharedPreferencesManager.putString(SharedPreferencesManager.keyRefreshToken, token.refreshToken);
  157. await _sharedPreferencesManager.putInt(SharedPreferencesManager.keyCountRefreshToken, 0);
  158. }
  159. static Future<bool> clearPreferences() async {
  160. await _sharedPreferencesManager.clearKey(SharedPreferencesManager.keyAccessToken);
  161. await _sharedPreferencesManager.clearKey(SharedPreferencesManager.keyRefreshToken);
  162. await _sharedPreferencesManager.clearKey(SharedPreferencesManager.keyUsername);
  163. await _sharedPreferencesManager.clearKey(SharedPreferencesManager.keyIsLogin);
  164. await _sharedPreferencesManager.clearKey(SharedPreferencesManager.keyScoope);
  165. await _sharedPreferencesManager.clearKey(SharedPreferencesManager.debugString);
  166. await _sharedPreferencesManager.clearKey(SharedPreferencesManager.keyMenuDisplay);
  167. return true;
  168. }
  169. static setChangedPassword(val) async {
  170. _hasChangedPassword = val;
  171. }
  172. static bool getChangedPassword() {
  173. return _hasChangedPassword;
  174. }
  175. static setInternetStatus(val) async {
  176. _connected = val;
  177. }
  178. static bool getInternetStatus() {
  179. return _connected??true;
  180. }
  181. static setLoadAfterRequest(val) async {
  182. _loadAfterRequest = val;
  183. }
  184. static bool getLoadAfterRequest() {
  185. return _loadAfterRequest;
  186. }
  187. static Future<dynamic> getUserData(context) async {
  188. if (_userData == null) {
  189. try {
  190. _userData = await token.getUserData(context);
  191. } catch (error) {
  192. print(error.toString());
  193. U.showDebugToast(error.toString());
  194. return Future.error(error);
  195. }
  196. }
  197. return Future.value(_userData);
  198. }
  199. static Future<dynamic> reloadLicense() async {
  200. _license = null;
  201. return getLicense();
  202. }
  203. static Future<dynamic>? getLicense({showErr = true}) async {
  204. if (_license == null) {
  205. try {
  206. var dt = await ApiAuthProvider().getJsonDataNoAuth('/api/license');
  207. _license = dt;
  208. } catch (error) {
  209. if(showErr){
  210. Fluttertoast.showToast(msg: 'invalid_bridge'.tr());
  211. }
  212. // print(error.toString());
  213. // U.showDebugToast(error.toString());
  214. return Future.error(error);
  215. }
  216. }
  217. return Future.value(_license);
  218. }
  219. static bool? isDebug() {
  220. return _sharedPreferencesManager.getBool(SharedPreferencesManager.keyIsDebug);
  221. }
  222. static bool? isLoggedIn() {
  223. return _sharedPreferencesManager.getBool(SharedPreferencesManager.keyIsLogin) != null ? _sharedPreferencesManager.getBool(SharedPreferencesManager.keyIsLogin) : false;
  224. }
  225. static int? getVersion() {
  226. return _sharedPreferencesManager.getInt(SharedPreferencesManager.version);
  227. }
  228. static String? getAccessCode() {
  229. return _sharedPreferencesManager.getString(SharedPreferencesManager.keyAccessCode) == null || _sharedPreferencesManager.getString(SharedPreferencesManager.keyAccessCode) == '' ? null :
  230. _sharedPreferencesManager.getString(SharedPreferencesManager.keyAccessCode)!.contains("=") ?
  231. Uri.encodeComponent(_sharedPreferencesManager.getString(SharedPreferencesManager.keyAccessCode)!) :
  232. _sharedPreferencesManager.getString(SharedPreferencesManager.keyAccessCode);
  233. }
  234. static String? getBaseUrl() {
  235. return _sharedPreferencesManager.getString(SharedPreferencesManager.keyBaseUrl);
  236. }
  237. static bool servantDisplay() {
  238. if(_sharedPreferencesManager.isKeyExists(SharedPreferencesManager.keyMenuDisplay)!){
  239. return _sharedPreferencesManager.getBool(SharedPreferencesManager.keyMenuDisplay)!;
  240. }
  241. return false;
  242. }
  243. static void setServantDisplay(bool servant) async {
  244. await _sharedPreferencesManager.putBool(SharedPreferencesManager.keyMenuDisplay, servant);
  245. }
  246. static bool autoTranslate() {
  247. if(_sharedPreferencesManager.isKeyExists(SharedPreferencesManager.keyAutoTranslate)!){
  248. return _sharedPreferencesManager.getBool(SharedPreferencesManager.keyAutoTranslate)!;
  249. }
  250. return false;
  251. }
  252. static void setAutoTranslate(bool translate) async {
  253. await _sharedPreferencesManager.putBool(SharedPreferencesManager.keyAutoTranslate, translate);
  254. }
  255. static void clearAccessCode() async {
  256. // print("accCode cleared!!");
  257. await _sharedPreferencesManager.clearKey(SharedPreferencesManager.keyAccessCode);
  258. return;
  259. }
  260. static String? getSerialCode() {
  261. return _sharedPreferencesManager.getString(SharedPreferencesManager.keySerialCode);
  262. }
  263. static int _serverVersion = 0;
  264. static final Completer<void> _versionReady = Completer<void>();
  265. static List validLang = [];
  266. static getServerVersion() async{
  267. String url = '/api/license';
  268. try {
  269. var dt = await ApiAuthProvider().getJsonDataNoAuth(url);
  270. _serverVersion = dt['serverVersion'];
  271. validLang = newServerVersion(1754624839) ? dt["_validLang"] : dt['languages'];
  272. CacheMan.writeData(url, _serverVersion);
  273. _versionReady.complete();
  274. } catch (error) {
  275. var val = await CacheMan.readData(url);
  276. if (val != null) {
  277. _serverVersion = val['data'];
  278. }
  279. // print("U checkServerVersion error: ${error.toString()}");
  280. }
  281. // print('checking current server version: $_serverVersion');
  282. }
  283. static Future<void> _waitUntilServerVersionReady() async {
  284. if (!_versionReady.isCompleted) {
  285. await _versionReady.future;
  286. }
  287. }
  288. static String getLang(code){
  289. if(code is int){
  290. return validLang[code+1];
  291. } else {
  292. return code;
  293. }
  294. }
  295. static String getLangIndex(code){
  296. if(code == 'id' || code == 'en'){
  297. return code;
  298. } else {
  299. var t = validLang.indexOf(code)-1;
  300. return t.toString();
  301. }
  302. }
  303. static List retValidLang(){
  304. return validLang;
  305. }
  306. static newServerVersion(int version){
  307. return version <= _serverVersion;
  308. }
  309. static final Map<String, Future<bool>> _compatibilityCache = {};
  310. static Future<bool> isCompatibleWith(VersionKey key) {
  311. final keyName = key.name.toString();
  312. if (_compatibilityCache.containsKey(keyName)) {
  313. return _compatibilityCache[keyName]!;
  314. }
  315. final future = _loadAndCompare(keyName);
  316. _compatibilityCache[keyName] = future;
  317. return future;
  318. }
  319. static Future<bool> _loadAndCompare(String keyName) async {
  320. try{
  321. await _waitUntilServerVersionReady();
  322. final value = C.get(keyName);
  323. return value <= _serverVersion;
  324. }catch(e){
  325. return false;
  326. }
  327. }
  328. static int retServerVersion(){
  329. return _serverVersion;
  330. }
  331. static Map _otherLabelList = {};
  332. static getOtherLabelList(BuildContext context) async{
  333. if(newServerVersion(1725245109)){
  334. var res = await ApiAuthProvider().getData('/api/systemSettings/search/additional', {'key': 'request-for-other'}, context);
  335. if(res != null){
  336. _otherLabelList = res;
  337. }
  338. }
  339. }
  340. static otherLabelList(){
  341. return _otherLabelList;
  342. }
  343. static void showDebugToast(String msg) {
  344. if (_sharedPreferencesManager.getBool(SharedPreferencesManager.keyIsDebug)!) {
  345. Fluttertoast.showToast(
  346. msg: "Debug:" + msg,
  347. toastLength: Toast.LENGTH_SHORT,
  348. gravity: ToastGravity.BOTTOM,
  349. timeInSecForIosWeb: 1,
  350. backgroundColor: Colors.red,
  351. textColor: Colors.white,
  352. fontSize: 16.0);
  353. }
  354. }
  355. static double bodyWidth(context) {
  356. var width = MediaQuery.of(context).size.width;
  357. var height = MediaQuery.of(context).size.height;
  358. var portrait = !(width * 3 / 4 > height);
  359. var bodyWidth = portrait ? width : width / 2;
  360. if (bodyWidth < 500) {
  361. if (width < 500) {
  362. bodyWidth = width;
  363. } else {
  364. bodyWidth = 500;
  365. }
  366. }
  367. return bodyWidth;
  368. }
  369. static bool webView(BuildContext context){
  370. if(kIsWeb && MediaQuery.of(context).size.width >= 1000){
  371. return true;
  372. }
  373. return false;
  374. }
  375. static String rewriteUrl(String encrypted){
  376. var targetString = encrypted;
  377. if(encrypted.contains('/')){
  378. targetString = encrypted.split("/").first;
  379. }
  380. var baseUrl = decodeBase64Url(targetString);
  381. if(!baseUrl.contains('https://') && !baseUrl.contains('http://')){
  382. if(baseUrl.contains('://')){
  383. baseUrl = 'https://'+(baseUrl.split('://')[1]);
  384. }
  385. else{
  386. baseUrl = 'https://'+baseUrl;
  387. }
  388. }
  389. if(baseUrl.substring(baseUrl.length - 1) != '/'){
  390. baseUrl = baseUrl+'/';
  391. }
  392. // print(baseUrl);
  393. return encodeBase64Url(baseUrl);
  394. }
  395. static String encodeBase64Url(String encrypted){
  396. try {
  397. return stringToBase64Url.encode(encrypted);
  398. } catch (error) {
  399. throw error;
  400. }
  401. }
  402. static String decodeBase64Url(String encrypted){
  403. try {
  404. return stringToBase64Url.decode(encrypted);
  405. } catch (error) {
  406. throw error;
  407. }
  408. }
  409. static String getUrl() {
  410. return _url;
  411. }
  412. static void setUrl(String url) async {
  413. _url = url;
  414. return;
  415. }
  416. static void clearUrl() {
  417. _url = "";
  418. }
  419. static String getPidFromUrl(String url){
  420. // print("U => url : $url");
  421. if (url.contains("/loginme")) {
  422. url = url.split("/loginme").first;
  423. }
  424. if (!url.contains("=")) {
  425. url = Uri.decodeComponent(url);
  426. }
  427. url = url.replaceAll('/app/', '');
  428. // if(url.contains('#')){
  429. // return Uri.encodeComponent(url);
  430. // }
  431. return Uri.encodeComponent(url.split('/').first);
  432. }
  433. static List<Color> defaultRainbowColors() {
  434. return [
  435. Colors.red,
  436. Colors.orange,
  437. Colors.yellow,
  438. Colors.green,
  439. Colors.blue,
  440. Colors.indigo,
  441. Colors.purple,
  442. ];
  443. }
  444. static Widget iconsax(String name, {Color color = Colors.black, double size = 24}){
  445. return SvgPicture.asset(
  446. 'assets/iconsax/${name}.svg',
  447. colorFilter: ColorFilter.mode(color, BlendMode.srcIn),
  448. width: size, height: size,
  449. fit: BoxFit.scaleDown,
  450. matchTextDirection: true,
  451. );
  452. }
  453. static Options options = Options(format: Format.hex, luminosity: Luminosity.dark, colorType: [ColorType.red, ColorType.green, ColorType.blue, ColorType.orange]);
  454. static Map<String, dynamic> colorList = {};
  455. static int getColor(String name){
  456. try {
  457. if(!colorList.containsKey(name)){
  458. var color;
  459. do{
  460. color = int.parse(RandomColor.getColor(options).replaceAll('#', '0xff'));
  461. }while(colorList.containsValue(color));
  462. colorList[name] = color;
  463. }
  464. return colorList[name];
  465. } catch (e) {
  466. return 0xff000000;
  467. }
  468. }
  469. static String langColumn(BuildContext context, String text){
  470. var code = context.locale.toString();
  471. var prefix = code == 'id' || code == 'en' && text.substring(1) != '_' ? '' : '_';
  472. return code == 'id' ? text : '$prefix$text${code[0].toUpperCase()}${code.substring(1).toLowerCase()}';
  473. }
  474. static String realColumn(Locale loc, String text){
  475. var lc = loc.toString();
  476. if(lc == 'id' || lc == 'en'){
  477. if(lc == 'id') {
  478. return text;
  479. } else {
  480. return "${text}En";
  481. }
  482. } else {
  483. try {
  484. var i = validLang.indexOf(loc.toString()) - 1;
  485. return text = text + i.toString();
  486. } catch (e) {
  487. return text;
  488. }
  489. }
  490. }
  491. static bool hidePayload = false;
  492. static void setHidePayload(value) {
  493. hidePayload = value;
  494. }
  495. static checkPendingRequest(BuildContext context)async{
  496. List list = _sharedPreferencesManager.isKeyExists(SharedPreferencesManager.keyPendingData)!?jsonDecode(_sharedPreferencesManager.getString(SharedPreferencesManager.keyPendingData)!):[];
  497. List uniqueId = [];
  498. if(list.length > 0){
  499. showLoading(context);
  500. for(var element in list){
  501. var data = element['data'];
  502. if(element['others']){
  503. data['req'][0]['uniqueId'] = element['uniqueId'];
  504. data['req'][0]['images'] = element['imageList'];
  505. var res = await ApiAuthProvider().postData('/api/receptionists/send/request', null, data, context);
  506. if (res != null) {
  507. uniqueId.add(res['uniqueId']);
  508. // print('success send pending request others');
  509. }
  510. }
  511. else{
  512. data['uniqueId'] = element['uniqueId'];
  513. data['images'] = element['imageList'];
  514. var res = await ApiAuthProvider().postData('/api/requestHistories/search/request/' + element['type'] + '/' + element['id'].toString() + '/' + element['noteFormat'] + '/submit', null, data, context);
  515. if (res != null) {
  516. uniqueId.add(res['uniqueId']);
  517. // print('success send pending request');
  518. }
  519. }
  520. }
  521. uniqueId.forEach((id) {
  522. list.removeWhere((li) => li['uniqueId'] == id);
  523. });
  524. await _sharedPreferencesManager.putString(SharedPreferencesManager.keyPendingData, jsonEncode(list));
  525. closeLoading(context);
  526. }
  527. }
  528. static String renderStatus(String currentState){
  529. String title = '';
  530. if (currentState == 'DIPROSES') {
  531. title = 'stateRequested'.tr();
  532. } else if (currentState == 'DIMULAI') {
  533. title = 'stateDone'.tr();
  534. } else if (currentState == 'DISELESAIKAN' || currentState == 'TUNTAS') {
  535. title = 'stateFinish'.tr();
  536. } else if (currentState == 'DIBATALKAN') {
  537. title = 'stateCanceled'.tr();
  538. }
  539. return title;
  540. }
  541. }
  542. //@optionalTypeArgs
  543. // abstract class State<T extends StatefulWidget>
  544. @optionalTypeArgs
  545. abstract class SaveState<T extends StatefulWidget> extends State<T> {
  546. bool _disposed = false;
  547. @override
  548. void dispose() {
  549. _disposed = true;
  550. super.dispose();
  551. }
  552. @override
  553. void setState(VoidCallback fn) {
  554. if (!mounted || _disposed) {
  555. return;
  556. }
  557. super.setState(fn);
  558. }
  559. }