debug_util.dart 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. import 'dart:io';
  2. import 'dart:developer' as devtools;
  3. import 'dart:math' as math;
  4. import 'dart:convert';
  5. import 'package:flutter/foundation.dart';
  6. import 'package:flutter/material.dart';
  7. import '/main.dart';
  8. import '/flutter_flow/flutter_flow_theme.dart';
  9. import 'flutter_flow_util.dart';
  10. import 'package:collection/collection.dart';
  11. import 'package:easy_debounce/easy_debounce.dart';
  12. import 'package:debug_panel_proto/debug_panel_proto.dart';
  13. import '/auth/custom_auth/auth_util.dart';
  14. bool kEnableDebugLogging = true;
  15. /// A inherited widget that provides the root model of the current page, as well
  16. /// as a callback to link the current model to its parent model for debug logging
  17. /// purpose.
  18. class DebugFlutterFlowModelContext extends InheritedWidget {
  19. const DebugFlutterFlowModelContext({
  20. super.key,
  21. required this.rootModel,
  22. this.parentModelCallback,
  23. required super.child,
  24. });
  25. final FlutterFlowModel rootModel;
  26. final Function(FlutterFlowModel)? parentModelCallback;
  27. static DebugFlutterFlowModelContext? maybeOf(BuildContext context) {
  28. return context
  29. .dependOnInheritedWidgetOfExactType<DebugFlutterFlowModelContext>();
  30. }
  31. static DebugFlutterFlowModelContext of(BuildContext context) {
  32. final DebugFlutterFlowModelContext? result = maybeOf(context);
  33. assert(result != null, 'No DebugFlutterFlowModelContext found in context');
  34. return result!;
  35. }
  36. @override
  37. bool updateShouldNotify(DebugFlutterFlowModelContext oldWidget) =>
  38. rootModel != oldWidget.rootModel ||
  39. parentModelCallback != oldWidget.parentModelCallback;
  40. }
  41. /// replace ModalRoute.of(context), needed because of the issue in Flutter 3.19.x
  42. /// see discussion https://github.com/flutter/flutter/issues/146132 and
  43. /// https://github.com/flutter/flutter/pull/145389
  44. class DebugModalRoute {
  45. static ModalRoute<dynamic>? of(BuildContext context) {
  46. ModalRoute<dynamic>? route;
  47. context.visitAncestorElements((element) {
  48. if (element.widget.runtimeType.toString() == '_ModalScopeStatus') {
  49. dynamic widget = element.widget;
  50. route = widget.route as ModalRoute;
  51. return false;
  52. }
  53. return true;
  54. });
  55. return route;
  56. }
  57. }
  58. extension SerializationExtensions on GeneratedMessage {
  59. String get serializedBufferString => base64.encode(writeToBuffer());
  60. }
  61. void debugLogging(String info) {
  62. devtools.postEvent(
  63. 'ext.flutterflow_debug_panel.updateDebugData',
  64. {'data': info},
  65. );
  66. }
  67. /// Debounce the logging call for different channel (tag) every 500ms
  68. void debouncedDebugLogging(
  69. String tag,
  70. Map<String, dynamic> Function() debugInfo,
  71. ) {
  72. if (!kEnableDebugLogging) {
  73. return;
  74. }
  75. try {
  76. EasyDebounce.debounce(
  77. tag,
  78. const Duration(milliseconds: 1000),
  79. () => debugLogging(json.encode(debugInfo())),
  80. );
  81. } catch (_) {}
  82. }
  83. void debugLogGlobalProperty(
  84. BuildContext context, {
  85. String? locale,
  86. String? routePath,
  87. List<String>? routeStack,
  88. }) async {
  89. debouncedDebugLogging(
  90. '405ebf2ff50c295c675b5802889ea941f081fd51',
  91. () => {
  92. 'event_type': 'variable',
  93. 'data_source': 'globalProperty',
  94. 'data': GlobalPropertyDebugData(
  95. values: context.mounted
  96. ? {
  97. 'screenWidth': debugSerializeParam(
  98. MediaQuery.sizeOf(context).width,
  99. ParamType.double,
  100. nullable: false,
  101. ),
  102. 'screenHeight': debugSerializeParam(
  103. MediaQuery.sizeOf(context).height,
  104. ParamType.double,
  105. nullable: false,
  106. ),
  107. 'platform': debugSerializeParam(
  108. kIsWeb ? 'web' : Platform.operatingSystem,
  109. ParamType.String,
  110. nullable: false,
  111. ),
  112. 'themeMode': debugSerializeParam(
  113. FlutterFlowTheme.themeMode.name,
  114. ParamType.String,
  115. nullable: false,
  116. ),
  117. 'currentTime': debugSerializeParam(
  118. getCurrentTimestamp,
  119. ParamType.DateTime,
  120. nullable: false,
  121. ),
  122. 'locale': debugSerializeParam(
  123. locale ?? MyApp.of(context).locale?.toString(),
  124. ParamType.String,
  125. nullable: true,
  126. ),
  127. 'route': debugSerializeParam(
  128. (routePath ?? MyApp.of(context).getRoute())
  129. .toString(),
  130. ParamType.String,
  131. nullable: false,
  132. link: debugRouteLinkMap[
  133. (routePath ?? MyApp.of(context).getRoute())
  134. .toString()],
  135. ),
  136. 'routeStack': DebugDataField(
  137. type: DebugDataField_ParamType.STRING,
  138. listValue: ListDebugDataField(
  139. values: (routeStack ??
  140. MyApp.of(context).getRouteStack())
  141. .map((e) => DebugDataField(
  142. type: DebugDataField_ParamType.STRING,
  143. serializedValue: e,
  144. link: debugRouteLinkMap[e],
  145. nullable: false,
  146. ))
  147. .toList(),
  148. ),
  149. nullable: false,
  150. ),
  151. }.entries
  152. : [])
  153. .serializedBufferString
  154. });
  155. }
  156. void debugLogAppState(FFAppState appState) {
  157. debouncedDebugLogging(
  158. 'fbcc19a787981a30d86b10103c2f3951604b2ae6',
  159. () => {
  160. 'event_type': 'variable',
  161. 'data_source': 'appState',
  162. 'data': AppStateDebugData(
  163. values: appState.toDebugSerializableMap().entries)
  164. .serializedBufferString,
  165. });
  166. }
  167. void debugLogAuthenticatedUser() {
  168. debouncedDebugLogging(
  169. 'c0186d2c21d5d9300ee148206df9fbd1850b8d41',
  170. () => {
  171. 'event_type': 'variable',
  172. 'data_source': 'authenticatedUser',
  173. 'data': AuthenticatedUserDebugData(
  174. values: {
  175. 'isUserLoggedIn': debugSerializeParam(
  176. loggedIn,
  177. ParamType.bool,
  178. nullable: false,
  179. ),
  180. 'currentUserUid': debugSerializeParam(
  181. currentUserUid,
  182. ParamType.String,
  183. nullable: false,
  184. ),
  185. 'currentAuthenticationToken': debugSerializeParam(
  186. currentAuthenticationToken,
  187. ParamType.String,
  188. nullable: true,
  189. ),
  190. 'currentAuthRefreshToken': debugSerializeParam(
  191. currentAuthRefreshToken,
  192. ParamType.String,
  193. nullable: true,
  194. ),
  195. 'currentAuthTokenExpiration': debugSerializeParam(
  196. currentAuthTokenExpiration,
  197. ParamType.DateTime,
  198. nullable: true,
  199. ),
  200. 'currentUserData': debugSerializeParam(
  201. currentUserData, ParamType.DataStruct,
  202. nullable: true, name: 'User'),
  203. }.entries)
  204. .serializedBufferString,
  205. });
  206. }
  207. void debugLogWidgetClass(FlutterFlowModel widgetClassModel) {
  208. WidgetsBinding.instance.addPostFrameCallback(
  209. (_) {
  210. if (widgetClassModel.isRouteVisible) {
  211. debouncedDebugLogging(
  212. '508f3c74205c87928b71f49040062e732f9c20b0',
  213. () => {
  214. 'event_type': 'variable',
  215. 'data_source': 'widgetClass',
  216. 'data': widgetClassModel.rootModel
  217. .toWidgetClassDebugData()
  218. .serializedBufferString,
  219. });
  220. }
  221. },
  222. );
  223. }
  224. mixin DebugLoggable {
  225. Function()? logger;
  226. void debugLog() {
  227. logger?.call();
  228. }
  229. }
  230. class LoggableList<E> extends DelegatingList<E> with DebugLoggable {
  231. LoggableList(super.base);
  232. @override
  233. void operator []=(int index, E value) {
  234. super[index] = value;
  235. debugLog();
  236. }
  237. @override
  238. void add(E value) {
  239. super.add(value);
  240. debugLog();
  241. }
  242. @override
  243. void addAll(Iterable<E> iterable) {
  244. super.addAll(iterable);
  245. debugLog();
  246. }
  247. @override
  248. void clear() {
  249. super.clear();
  250. debugLog();
  251. }
  252. @override
  253. void fillRange(int start, int end, [E? fillValue]) {
  254. super.fillRange(start, end, fillValue);
  255. debugLog();
  256. }
  257. @override
  258. set first(E value) {
  259. if (isEmpty) throw RangeError.index(0, this);
  260. this[0] = value;
  261. debugLog();
  262. }
  263. @override
  264. void insert(int index, E element) {
  265. super.insert(index, element);
  266. debugLog();
  267. }
  268. @override
  269. void insertAll(int index, Iterable<E> iterable) {
  270. super.insertAll(index, iterable);
  271. debugLog();
  272. }
  273. @override
  274. set last(E value) {
  275. if (isEmpty) throw RangeError.index(0, this);
  276. this[length - 1] = value;
  277. debugLog();
  278. }
  279. @override
  280. bool remove(Object? value) {
  281. var rst = super.remove(value);
  282. debugLog();
  283. return rst;
  284. }
  285. @override
  286. E removeAt(int index) {
  287. var rst = super.removeAt(index);
  288. debugLog();
  289. return rst;
  290. }
  291. @override
  292. E removeLast() {
  293. var rst = super.removeLast();
  294. debugLog();
  295. return rst;
  296. }
  297. @override
  298. void removeRange(int start, int end) {
  299. super.removeRange(start, end);
  300. debugLog();
  301. }
  302. @override
  303. void removeWhere(bool Function(E) test) {
  304. super.removeWhere(test);
  305. debugLog();
  306. }
  307. @override
  308. void replaceRange(int start, int end, Iterable<E> iterable) {
  309. super.replaceRange(start, end, iterable);
  310. debugLog();
  311. }
  312. @override
  313. void retainWhere(bool Function(E) test) {
  314. super.retainWhere(test);
  315. debugLog();
  316. }
  317. @override
  318. void setAll(int index, Iterable<E> iterable) {
  319. super.setAll(index, iterable);
  320. debugLog();
  321. }
  322. @override
  323. void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
  324. super.setRange(start, end, iterable, skipCount);
  325. debugLog();
  326. }
  327. @override
  328. void shuffle([math.Random? random]) {
  329. super.shuffle(random);
  330. debugLog();
  331. }
  332. @override
  333. void sort([int Function(E, E)? compare]) {
  334. super.sort(compare);
  335. debugLog();
  336. }
  337. }
  338. class LoggableMap<K, V> extends DelegatingMap<K, V> with DebugLoggable {
  339. LoggableMap(super.base);
  340. @override
  341. void operator []=(K key, V value) {
  342. super[key] = value;
  343. debugLog();
  344. }
  345. @override
  346. void addAll(Map<K, V> other) {
  347. super.addAll(other);
  348. debugLog();
  349. }
  350. @override
  351. void addEntries(Iterable<MapEntry<K, V>> entries) {
  352. super.addEntries(entries);
  353. debugLog();
  354. }
  355. @override
  356. void clear() {
  357. super.clear();
  358. debugLog();
  359. }
  360. @override
  361. void forEach(void Function(K, V) f) {
  362. super.forEach(f);
  363. debugLog();
  364. }
  365. @override
  366. V putIfAbsent(K key, V Function() ifAbsent) {
  367. var rst = super.putIfAbsent(key, ifAbsent);
  368. debugLog();
  369. return rst;
  370. }
  371. @override
  372. V? remove(Object? key) {
  373. var rst = super.remove(key);
  374. debugLog();
  375. return rst;
  376. }
  377. @override
  378. void removeWhere(bool Function(K, V) test) {
  379. super.removeWhere(test);
  380. debugLog();
  381. }
  382. @override
  383. V update(K key, V Function(V) update, {V Function()? ifAbsent}) {
  384. var rst = super.update(key, update, ifAbsent: ifAbsent);
  385. debugLog();
  386. return rst;
  387. }
  388. @override
  389. void updateAll(V Function(K, V) update) {
  390. var rst = super.updateAll(update);
  391. debugLog();
  392. return rst;
  393. }
  394. }