debug_util.dart 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  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. 'currentTime': debugSerializeParam(
  113. getCurrentTimestamp,
  114. ParamType.DateTime,
  115. nullable: false,
  116. ),
  117. 'locale': debugSerializeParam(
  118. locale ?? MyApp.of(context).locale?.toString(),
  119. ParamType.String,
  120. nullable: true,
  121. ),
  122. 'route': debugSerializeParam(
  123. (routePath ?? MyApp.of(context).getRoute())
  124. .toString(),
  125. ParamType.String,
  126. nullable: false,
  127. link: debugRouteLinkMap[
  128. (routePath ?? MyApp.of(context).getRoute())
  129. .toString()],
  130. ),
  131. 'routeStack': DebugDataField(
  132. type: DebugDataField_ParamType.STRING,
  133. listValue: ListDebugDataField(
  134. values: (routeStack ??
  135. MyApp.of(context).getRouteStack())
  136. .map((e) => DebugDataField(
  137. type: DebugDataField_ParamType.STRING,
  138. serializedValue: e,
  139. link: debugRouteLinkMap[e],
  140. nullable: false,
  141. ))
  142. .toList(),
  143. ),
  144. nullable: false,
  145. ),
  146. }.entries
  147. : [])
  148. .serializedBufferString
  149. });
  150. }
  151. void debugLogAppState(FFAppState appState) {
  152. debouncedDebugLogging(
  153. 'fbcc19a787981a30d86b10103c2f3951604b2ae6',
  154. () => {
  155. 'event_type': 'variable',
  156. 'data_source': 'appState',
  157. 'data': AppStateDebugData(
  158. values: appState.toDebugSerializableMap().entries)
  159. .serializedBufferString,
  160. });
  161. }
  162. void debugLogAuthenticatedUser() {
  163. debouncedDebugLogging(
  164. 'c0186d2c21d5d9300ee148206df9fbd1850b8d41',
  165. () => {
  166. 'event_type': 'variable',
  167. 'data_source': 'authenticatedUser',
  168. 'data': AuthenticatedUserDebugData(
  169. values: {
  170. 'isUserLoggedIn': debugSerializeParam(
  171. loggedIn,
  172. ParamType.bool,
  173. nullable: false,
  174. ),
  175. 'currentUserUid': debugSerializeParam(
  176. currentUserUid,
  177. ParamType.String,
  178. nullable: false,
  179. ),
  180. 'currentAuthenticationToken': debugSerializeParam(
  181. currentAuthenticationToken,
  182. ParamType.String,
  183. nullable: true,
  184. ),
  185. 'currentAuthRefreshToken': debugSerializeParam(
  186. currentAuthRefreshToken,
  187. ParamType.String,
  188. nullable: true,
  189. ),
  190. 'currentAuthTokenExpiration': debugSerializeParam(
  191. currentAuthTokenExpiration,
  192. ParamType.DateTime,
  193. nullable: true,
  194. ),
  195. 'currentUserData': debugSerializeParam(
  196. currentUserData, ParamType.DataStruct,
  197. nullable: true, name: 'User'),
  198. }.entries)
  199. .serializedBufferString,
  200. });
  201. }
  202. void debugLogWidgetClass(FlutterFlowModel widgetClassModel) {
  203. WidgetsBinding.instance.addPostFrameCallback(
  204. (_) {
  205. if (widgetClassModel.isRouteVisible) {
  206. debouncedDebugLogging(
  207. '508f3c74205c87928b71f49040062e732f9c20b0',
  208. () => {
  209. 'event_type': 'variable',
  210. 'data_source': 'widgetClass',
  211. 'data': widgetClassModel.rootModel
  212. .toWidgetClassDebugData()
  213. .serializedBufferString,
  214. });
  215. }
  216. },
  217. );
  218. }
  219. mixin DebugLoggable {
  220. Function()? logger;
  221. void debugLog() {
  222. logger?.call();
  223. }
  224. }
  225. class LoggableList<E> extends DelegatingList<E> with DebugLoggable {
  226. LoggableList(super.base);
  227. @override
  228. void operator []=(int index, E value) {
  229. super[index] = value;
  230. debugLog();
  231. }
  232. @override
  233. void add(E value) {
  234. super.add(value);
  235. debugLog();
  236. }
  237. @override
  238. void addAll(Iterable<E> iterable) {
  239. super.addAll(iterable);
  240. debugLog();
  241. }
  242. @override
  243. void clear() {
  244. super.clear();
  245. debugLog();
  246. }
  247. @override
  248. void fillRange(int start, int end, [E? fillValue]) {
  249. super.fillRange(start, end, fillValue);
  250. debugLog();
  251. }
  252. @override
  253. set first(E value) {
  254. if (isEmpty) throw RangeError.index(0, this);
  255. this[0] = value;
  256. debugLog();
  257. }
  258. @override
  259. void insert(int index, E element) {
  260. super.insert(index, element);
  261. debugLog();
  262. }
  263. @override
  264. void insertAll(int index, Iterable<E> iterable) {
  265. super.insertAll(index, iterable);
  266. debugLog();
  267. }
  268. @override
  269. set last(E value) {
  270. if (isEmpty) throw RangeError.index(0, this);
  271. this[length - 1] = value;
  272. debugLog();
  273. }
  274. @override
  275. bool remove(Object? value) {
  276. var rst = super.remove(value);
  277. debugLog();
  278. return rst;
  279. }
  280. @override
  281. E removeAt(int index) {
  282. var rst = super.removeAt(index);
  283. debugLog();
  284. return rst;
  285. }
  286. @override
  287. E removeLast() {
  288. var rst = super.removeLast();
  289. debugLog();
  290. return rst;
  291. }
  292. @override
  293. void removeRange(int start, int end) {
  294. super.removeRange(start, end);
  295. debugLog();
  296. }
  297. @override
  298. void removeWhere(bool Function(E) test) {
  299. super.removeWhere(test);
  300. debugLog();
  301. }
  302. @override
  303. void replaceRange(int start, int end, Iterable<E> iterable) {
  304. super.replaceRange(start, end, iterable);
  305. debugLog();
  306. }
  307. @override
  308. void retainWhere(bool Function(E) test) {
  309. super.retainWhere(test);
  310. debugLog();
  311. }
  312. @override
  313. void setAll(int index, Iterable<E> iterable) {
  314. super.setAll(index, iterable);
  315. debugLog();
  316. }
  317. @override
  318. void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
  319. super.setRange(start, end, iterable, skipCount);
  320. debugLog();
  321. }
  322. @override
  323. void shuffle([math.Random? random]) {
  324. super.shuffle(random);
  325. debugLog();
  326. }
  327. @override
  328. void sort([int Function(E, E)? compare]) {
  329. super.sort(compare);
  330. debugLog();
  331. }
  332. }
  333. class LoggableMap<K, V> extends DelegatingMap<K, V> with DebugLoggable {
  334. LoggableMap(super.base);
  335. @override
  336. void operator []=(K key, V value) {
  337. super[key] = value;
  338. debugLog();
  339. }
  340. @override
  341. void addAll(Map<K, V> other) {
  342. super.addAll(other);
  343. debugLog();
  344. }
  345. @override
  346. void addEntries(Iterable<MapEntry<K, V>> entries) {
  347. super.addEntries(entries);
  348. debugLog();
  349. }
  350. @override
  351. void clear() {
  352. super.clear();
  353. debugLog();
  354. }
  355. @override
  356. void forEach(void Function(K, V) f) {
  357. super.forEach(f);
  358. debugLog();
  359. }
  360. @override
  361. V putIfAbsent(K key, V Function() ifAbsent) {
  362. var rst = super.putIfAbsent(key, ifAbsent);
  363. debugLog();
  364. return rst;
  365. }
  366. @override
  367. V? remove(Object? key) {
  368. var rst = super.remove(key);
  369. debugLog();
  370. return rst;
  371. }
  372. @override
  373. void removeWhere(bool Function(K, V) test) {
  374. super.removeWhere(test);
  375. debugLog();
  376. }
  377. @override
  378. V update(K key, V Function(V) update, {V Function()? ifAbsent}) {
  379. var rst = super.update(key, update, ifAbsent: ifAbsent);
  380. debugLog();
  381. return rst;
  382. }
  383. @override
  384. void updateAll(V Function(K, V) update) {
  385. var rst = super.updateAll(update);
  386. debugLog();
  387. return rst;
  388. }
  389. }