U.dart 18 KB

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