improve transaction list performance (#3082)
What changed, and why it matters
This commit is a routine user-interface performance improvement. It replaces several nested scrolling lists with Flutter's more efficient 'sliver' scrolling widgets, adds a small delay to a transaction-update callback, and updates a lightning-bolt icon asset. There is no indication it fixes a security vulnerability or introduces a security-relevant change.
No security action required. Treat as a normal UI/performance refactor and review for functional regressions in transaction list rendering.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch refactors the Cake Wallet home/dashboard transaction list to use CustomScrollView slivers (SliverMainAxisGroup, SliverList, SliverToBoxAdapter, SliverPadding) instead of shrink-wrapped ListViews inside a Column. It also changes the transaction-list update logic in DashboardViewModelBase from clearing and re-adding all items to only appending new TransactionListItem instances, and adds an equality operator based on txHash plus a 300 ms delay on the MobX reaction. A new SVG and vector icon are added for the Bitcoin/lightning indicator.
Changed components
lib/new-ui/pages/home_page.dartlib/new-ui/widgets/coins_page/assets_history/assets_history_section.dartlib/new-ui/widgets/coins_page/assets_history/assets_section.dartlib/new-ui/widgets/coins_page/assets_history/assets_top_bar.dartlib/new-ui/widgets/coins_page/assets_history/history_section.dartlib/new-ui/widgets/coins_page/assets_history/history_tile.dartlib/src/screens/dashboard/pages/nft_listing_page.dartlib/view_model/dashboard/dashboard_view_model.dartlib/view_model/dashboard/transaction_list_item.dartInspect captured patch +185 / −110
diff --git a/assets/new-ui/lightning-icon.svg.vec b/assets/new-ui/lightning-icon.svg.vec
new file mode 100644
index 00000000..09d9daa7
Binary files /dev/null and b/assets/new-ui/lightning-icon.svg.vec differ
diff --git a/lib/new-ui/pages/home_page.dart b/lib/new-ui/pages/home_page.dart
index 8da84dc5..c4fedb63 100644
--- a/lib/new-ui/pages/home_page.dart
+++ b/lib/new-ui/pages/home_page.dart
@@ -144,18 +144,21 @@ class _NewHomePageState extends State<NewHomePage> {
);
},
),
+
+ ],
+ ),
+ ),
Observer(
builder: (_) => AssetsHistorySection(
nftViewModel: widget.nftViewModel,
dashboardViewModel: widget.dashboardViewModel,
),
),
- SizedBox(height: 80.0)
- ],
- ),
- ),]
- ),
- Container(
+ SliverToBoxAdapter(
+ child: SizedBox(height: 80.0),
+ )
+ ]),
+ Container(
height: (MediaQuery.of(context).padding.top),
decoration: BoxDecoration(
gradient: LinearGradient(
diff --git a/lib/new-ui/widgets/coins_page/assets_history/assets_history_section.dart b/lib/new-ui/widgets/coins_page/assets_history/assets_history_section.dart
index 9eb7bc64..998ebc13 100644
--- a/lib/new-ui/widgets/coins_page/assets_history/assets_history_section.dart
+++ b/lib/new-ui/widgets/coins_page/assets_history/assets_history_section.dart
@@ -68,8 +68,8 @@ class _AssetsHistorySectionState extends State<AssetsHistorySection> {
@override
Widget build(BuildContext context) {
- return Column(
- children: [
+ return SliverMainAxisGroup(
+ slivers: [
// if(tabs.length>1)
AssetsTopBar(
dashboardViewModel: widget.dashboardViewModel,
diff --git a/lib/new-ui/widgets/coins_page/assets_history/assets_section.dart b/lib/new-ui/widgets/coins_page/assets_history/assets_section.dart
index e2d15eea..74990e29 100644
--- a/lib/new-ui/widgets/coins_page/assets_history/assets_section.dart
+++ b/lib/new-ui/widgets/coins_page/assets_history/assets_section.dart
@@ -15,45 +15,47 @@ class AssetsSection extends StatelessWidget {
@override
Widget build(BuildContext context) {
- return Padding(
- padding: const EdgeInsets.only(bottom: 64.0),
- child: Observer(
- builder: (context) {
- final hasMweb = dashboardViewModel.hasMweb && dashboardViewModel.mwebEnabled;
- return ListView.builder(
- shrinkWrap: true,
- padding: EdgeInsets.zero,
- physics: NeverScrollableScrollPhysics(),
- itemCount: dashboardViewModel.balanceViewModel.formattedBalances.length + (hasMweb ? 1 : 0),
- itemBuilder: (context, index) {
- return Observer(builder: (context) {
- if (hasMweb) {
+ return SliverToBoxAdapter(
+ child: Padding(
+ padding: const EdgeInsets.only(bottom: 64.0),
+ child: Observer(
+ builder: (context) {
+ final hasMweb = dashboardViewModel.hasMweb && dashboardViewModel.mwebEnabled;
+ return ListView.builder(
+ shrinkWrap: true,
+ padding: EdgeInsets.zero,
+ physics: NeverScrollableScrollPhysics(),
+ itemCount: dashboardViewModel.balanceViewModel.formattedBalances.length + (hasMweb ? 1 : 0),
+ itemBuilder: (context, index) {
+ return Observer(builder: (context) {
+ if (hasMweb) {
+ return AssetTile(
+ showSwap: dashboardViewModel.isEnabledSwapAction,
+ balance: dashboardViewModel.balanceViewModel.formattedBalances.first,
+ showSecondary: index > 0 ? true : false,
+ wallet: dashboardViewModel.wallet,
+ chainIconPath: index > 0 ? dashboardViewModel.wallet.currency.chainIconPath! : "",
+ trailingText: index > 0 ? "MWEB" : null,
+ modalMode: index > 0
+ ? AssetDetailsModalModes.ltcPrivate
+ : AssetDetailsModalModes.ltcTransparent,
+ title: index > 0 ? "Litecoin Private" : null,
+ );
+ }
+
+ final balance = dashboardViewModel.balanceViewModel.formattedBalances.elementAt(index);
return AssetTile(
showSwap: dashboardViewModel.isEnabledSwapAction,
- balance: dashboardViewModel.balanceViewModel.formattedBalances.first,
- showSecondary: index > 0 ? true : false,
+ balance: balance,
wallet: dashboardViewModel.wallet,
- chainIconPath: index > 0 ? dashboardViewModel.wallet.currency.chainIconPath! : "",
- trailingText: index > 0 ? "MWEB" : null,
- modalMode: index > 0
- ? AssetDetailsModalModes.ltcPrivate
- : AssetDetailsModalModes.ltcTransparent,
- title: index > 0 ? "Litecoin Private" : null,
+ chainIconPath: _getChainIconPath(),
);
- }
-
- final balance = dashboardViewModel.balanceViewModel.formattedBalances.elementAt(index);
- return AssetTile(
- showSwap: dashboardViewModel.isEnabledSwapAction,
- balance: balance,
- wallet: dashboardViewModel.wallet,
- chainIconPath: _getChainIconPath(),
- );
- });
-
- },
- );
- }
+ });
+
+ },
+ );
+ }
+ ),
),
);
}
diff --git a/lib/new-ui/widgets/coins_page/assets_history/assets_top_bar.dart b/lib/new-ui/widgets/coins_page/assets_history/assets_top_bar.dart
index bec40bfd..c2a19f5f 100644
--- a/lib/new-ui/widgets/coins_page/assets_history/assets_top_bar.dart
+++ b/lib/new-ui/widgets/coins_page/assets_history/assets_top_bar.dart
@@ -26,10 +26,10 @@ class AssetsTopBar extends StatelessWidget {
final settingsButtonText = _getSettingsButtonText();
final hasTokenSettingsButton = settingsButtonText != null;
-
- return Padding(
- padding: const EdgeInsets.only(top: 12.0, bottom: 12.0, left: 12.0, right: 18.0),
- child: Row(
+ return SliverToBoxAdapter(
+ child: Padding(
+ padding: const EdgeInsets.only(top: 12.0, bottom: 12.0, left: 12.0, right: 18.0),
+ child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
@@ -82,9 +82,9 @@ class AssetsTopBar extends StatelessWidget {
),
),
),
- ),
-
- ],
+ ),
+ ],
+ ),
),
);
}
diff --git a/lib/new-ui/widgets/coins_page/assets_history/history_section.dart b/lib/new-ui/widgets/coins_page/assets_history/history_section.dart
index fd1617fe..8ee96083 100644
--- a/lib/new-ui/widgets/coins_page/assets_history/history_section.dart
+++ b/lib/new-ui/widgets/coins_page/assets_history/history_section.dart
@@ -27,26 +27,29 @@ class HistorySection extends StatelessWidget {
@override
Widget build(BuildContext context) {
- return Padding(
- padding: const EdgeInsets.symmetric(horizontal: 24.0),
- child: Observer(
- builder: (_) => (dashboardViewModel.items.isEmpty &&
- dashboardViewModel.status is! SyncingSyncStatus)
- ? Padding(
- padding: EdgeInsets.only(top: 24),
- child: Text(S.of(context).transactions_will_appear_here,
- style: TextStyle(
- fontSize: 14,
- fontWeight: FontWeight.w400,
- color: Theme.of(context).colorScheme.onSurfaceVariant)))
- : ListView.builder(
- physics: const NeverScrollableScrollPhysics(),
- padding: EdgeInsets.zero,
- shrinkWrap: true,
- itemCount: dashboardViewModel.items.length,
- itemBuilder: (context, index) => Observer(builder: (_) {
- final prevItem = index == 0 ? null : dashboardViewModel.items[index - 1];
- final item = dashboardViewModel.items[index];
+ return SliverPadding(
+ padding: const EdgeInsets.symmetric(horizontal: 24.0),
+ sliver: Observer(
+ builder: (_) => (dashboardViewModel.items.isEmpty &&
+ dashboardViewModel.status is! SyncingSyncStatus)
+ ? SliverPadding(
+ padding: EdgeInsets.only(top: 24),
+ sliver: SliverToBoxAdapter(
+ child: Center(
+ child: Text(S.of(context).transactions_will_appear_here,
+ style: TextStyle(
+ fontSize: 14,
+ fontWeight: FontWeight.w400,
+ color: Theme.of(context).colorScheme.onSurfaceVariant)),
+ ),
+ ),
+ )
+ : SliverList(
+ delegate: SliverChildBuilderDelegate(
+ childCount: dashboardViewModel.items.length,
+ (context, index) => Observer(builder: (_) {
+ final prevItem = index == 0 ? null : dashboardViewModel.items[index - 1];
+ final item = dashboardViewModel.items[index];
final nextItem = index == dashboardViewModel.items.length - 1
? null
: dashboardViewModel.items[index + 1];
@@ -163,6 +166,6 @@ class HistorySection extends StatelessWidget {
}),
),
),
- );
+ ));
}
}
diff --git a/lib/new-ui/widgets/coins_page/assets_history/history_tile.dart b/lib/new-ui/widgets/coins_page/assets_history/history_tile.dart
index ef4ed615..3fcbc8dd 100644
--- a/lib/new-ui/widgets/coins_page/assets_history/history_tile.dart
+++ b/lib/new-ui/widgets/coins_page/assets_history/history_tile.dart
@@ -63,7 +63,7 @@ class HistoryTile extends StatelessWidget {
return Stack(
children: [
CakeImageWidget(imageUrl:
- "assets/images/lightning-icon.svg",
+ "assets/new-ui/lightning-icon.svg",
width: 34,
height: 34,
),
diff --git a/lib/src/screens/dashboard/pages/nft_listing_page.dart b/lib/src/screens/dashboard/pages/nft_listing_page.dart
index c5930086..616c7bdf 100644
--- a/lib/src/screens/dashboard/pages/nft_listing_page.dart
+++ b/lib/src/screens/dashboard/pages/nft_listing_page.dart
@@ -31,38 +31,40 @@ class _NFTListingPageState extends State<NFTListingPage> {
@override
Widget build(BuildContext context) {
- return Observer(
- builder: (context) {
- return Column(
- children: [
- const SizedBox(height: 16),
- Padding(
- padding: const EdgeInsets.only(left: 16, right: 16, bottom: 16),
- child: PrimaryButton(
- text: S.current.import,
- color: Theme.of(context).colorScheme.surfaceContainer,
- textColor: Theme.of(context).colorScheme.onSecondaryContainer,
- onPressed: () => Navigator.pushNamed(
- context,
- Routes.importNFTPage,
- arguments: widget.nftViewModel,
+ return SliverToBoxAdapter(
+ child: Observer(
+ builder: (context) {
+ return Column(
+ children: [
+ const SizedBox(height: 16),
+ Padding(
+ padding: const EdgeInsets.only(left: 16, right: 16, bottom: 16),
+ child: PrimaryButton(
+ text: S.current.import,
+ color: Theme.of(context).colorScheme.surfaceContainer,
+ textColor: Theme.of(context).colorScheme.onSecondaryContainer,
+ onPressed: () => Navigator.pushNamed(
+ context,
+ Routes.importNFTPage,
+ arguments: widget.nftViewModel,
+ ),
),
),
- ),
- if (widget.nftViewModel.isLoading)
- Center(
- child: CircularProgressIndicator(
- backgroundColor: Theme.of(context).colorScheme.surfaceContainerHighest,
- valueColor: AlwaysStoppedAnimation<Color>(
- Theme.of(context).colorScheme.primary,
+ if (widget.nftViewModel.isLoading)
+ Center(
+ child: CircularProgressIndicator(
+ backgroundColor: Theme.of(context).colorScheme.surfaceContainerHighest,
+ valueColor: AlwaysStoppedAnimation<Color>(
+ Theme.of(context).colorScheme.primary,
+ ),
),
- ),
- )
- else
- NFTListWidget(nftViewModel: widget.nftViewModel)
- ],
- );
- },
+ )
+ else
+ NFTListWidget(nftViewModel: widget.nftViewModel)
+ ],
+ );
+ },
+ ),
);
}
}
diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart
index b92fb5d2..2a699e38 100644
--- a/lib/view_model/dashboard/dashboard_view_model.dart
+++ b/lib/view_model/dashboard/dashboard_view_model.dart
@@ -327,7 +327,7 @@ abstract class DashboardViewModelBase with Store {
} catch (_) {}
}
return length * confirmations;
- }, _transactionDisposerCallback);
+ }, _transactionDisposerCallback, delay: 300);
if (hasSilentPayments) {
silentPaymentsScanningActive = bitcoin!.getScanningActive(wallet);
@@ -481,13 +481,23 @@ abstract class DashboardViewModelBase with Store {
}
// printV("Transaction disposer callback (relevantTxs: ${relevantTxs.length} current: ${transactions.length})");
- transactions.clear();
- transactions.addAll(relevantTxs.map((tx) => TransactionListItem(
- transaction: tx,
- balanceViewModel: balanceViewModel,
- appStore: appStore,
- key: ValueKey('${wallet.type.name}_transaction_history_item_${tx.id}_key'),
- )));
+ final newTransactions = relevantTxs
+ .map((tx) => TransactionListItem(
+ transaction: tx,
+ balanceViewModel: balanceViewModel,
+ appStore: appStore,
+ key: ValueKey('${wallet.type.name}_transaction_history_item_${tx.id}_key'),
+ ))
+ .where((item) => !transactions.contains(item));
+
+ transactions.addAll(newTransactions);
+ // transactions.clear();
+ // transactions.addAll(relevantTxs.map((tx) => TransactionListItem(
+ // transaction: tx,
+ // balanceViewModel: balanceViewModel,
+ // appStore: appStore,
+ // key: ValueKey('${wallet.type.name}_transaction_history_item_${tx.id}_key'),
+ // )));
} finally {
_isTransactionDisposerCallbackRunning = false;
}
@@ -1252,7 +1262,7 @@ abstract class DashboardViewModelBase with Store {
} catch (_) {}
}
return length * confirmations;
- }, _transactionDisposerCallback);
+ }, _transactionDisposerCallback, delay: 300);
}
@action
diff --git a/lib/view_model/dashboard/transaction_list_item.dart b/lib/view_model/dashboard/transaction_list_item.dart
index e765e88c..de025e11 100644
--- a/lib/view_model/dashboard/transaction_list_item.dart
+++ b/lib/view_model/dashboard/transaction_list_item.dart
@@ -289,4 +289,12 @@ class TransactionListItem extends ActionListItem with Keyable {
@override
DateTime get date => transaction.date;
+
+ @override
+ bool operator ==(Object other) {
+ if (other is TransactionListItem) {
+ return other.transaction.txHash == transaction.txHash;
+ }
+ return false;
+ }
}
diff --git a/res/pictures/lightning-icon.svg b/res/pictures/lightning-icon.svg
new file mode 100644
index 00000000..272baa52
--- /dev/null
+++ b/res/pictures/lightning-icon.svg
@@ -0,0 +1,47 @@
+<svg width="250" height="250" viewBox="0 0 250 250" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M246.252 155.241C229.557 222.205 161.732 262.959 94.7596 246.26C27.8143 229.565 -12.9396 161.737 3.76352 94.7758C20.451 27.8031 88.2752 -12.9547 155.228 3.74061C222.197 20.4359 262.947 88.2719 246.252 155.241Z" fill="#F7931A"/>
+<path d="M246.252 155.241C229.557 222.205 161.732 262.959 94.7596 246.26C27.8143 229.565 -12.9396 161.737 3.76352 94.7758C20.451 27.8031 88.2752 -12.9547 155.228 3.74061C222.197 20.4359 262.947 88.2719 246.252 155.241Z" fill="url(#paint0_linear_14352_348907)"/>
+<path d="M246.252 155.241C229.557 222.205 161.732 262.959 94.7596 246.26C27.8143 229.565 -12.9396 161.737 3.76352 94.7758C20.451 27.8031 88.2752 -12.9547 155.228 3.74061C222.197 20.4359 262.947 88.2719 246.252 155.241Z" fill="url(#paint1_linear_14352_348907)"/>
+<path d="M246.252 155.241C229.557 222.205 161.732 262.959 94.7596 246.26C27.8143 229.565 -12.9396 161.737 3.76352 94.7758C20.451 27.8031 88.2752 -12.9547 155.228 3.74061C222.197 20.4359 262.947 88.2719 246.252 155.241Z" fill="url(#paint2_linear_14352_348907)"/>
+<path d="M3.76352 94.7757C20.4512 27.8033 88.2754 -12.9547 155.228 3.74058C222.197 20.4359 262.947 88.272 246.252 155.241L245.852 156.806C228.634 222.319 162.265 262.198 96.329 246.641L94.7597 246.26C27.8143 229.565 -12.9396 161.737 3.76352 94.7757ZM154.018 8.59214C89.7456 -7.43476 24.6351 31.6917 8.61509 95.9847V95.9866C-7.41942 160.268 31.7034 225.381 95.9686 241.408C160.262 257.44 225.373 218.317 241.4 154.032C257.428 89.7415 218.307 24.6193 154.018 8.59214Z" fill="url(#paint3_linear_14352_348907)"/>
+<path d="M3.76352 94.7757C20.4512 27.8033 88.2754 -12.9547 155.228 3.74058C222.197 20.4359 262.947 88.272 246.252 155.241L245.852 156.806C228.634 222.319 162.265 262.198 96.329 246.641L94.7597 246.26C27.8143 229.565 -12.9396 161.737 3.76352 94.7757ZM154.018 8.59214C89.7456 -7.43476 24.6351 31.6917 8.61509 95.9847V95.9866C-7.41942 160.268 31.7034 225.381 95.9686 241.408C160.262 257.44 225.373 218.317 241.4 154.032C257.428 89.7415 218.307 24.6193 154.018 8.59214Z" fill="url(#paint4_linear_14352_348907)"/>
+<path d="M3.76352 94.7757C20.4512 27.8033 88.2754 -12.9547 155.228 3.74058C222.197 20.4359 262.947 88.272 246.252 155.241L245.852 156.806C228.634 222.319 162.265 262.198 96.329 246.641L94.7597 246.26C27.8143 229.565 -12.9396 161.737 3.76352 94.7757ZM154.018 8.59214C89.7456 -7.43476 24.6351 31.6917 8.61509 95.9847V95.9866C-7.41942 160.268 31.7034 225.381 95.9686 241.408C160.262 257.44 225.373 218.317 241.4 154.032C257.428 89.7415 218.307 24.6193 154.018 8.59214Z" fill="url(#paint5_linear_14352_348907)"/>
+<path d="M59.8672 139.11L153.37 58.5384C157.444 55.9292 161.327 58.5384 158.841 63.0146L128.999 121.703H182.216C182.216 121.703 190.671 121.703 182.216 128.666L90.2058 209.734C83.7402 215.205 79.264 212.221 83.7402 203.766L112.587 146.57H59.8672C59.8672 146.57 51.4121 146.57 59.8672 139.11Z" fill="#F66E00"/>
+<path d="M59.8672 139.11L153.37 58.5384C157.444 55.9292 161.327 58.5384 158.841 63.0146L128.999 121.703H182.216C182.216 121.703 190.671 121.703 182.216 128.666L90.2058 209.734C83.7402 215.205 79.264 212.221 83.7402 203.766L112.587 146.57H59.8672C59.8672 146.57 51.4121 146.57 59.8672 139.11Z" fill="url(#paint6_linear_14352_348907)"/>
+<path d="M59.8672 129.11L153.37 48.5384C157.444 45.9292 161.327 48.5384 158.841 53.0146L128.999 111.703H182.216C182.216 111.703 190.671 111.703 182.216 118.666L90.2058 199.734C83.7402 205.205 79.264 202.221 83.7402 193.766L112.587 136.57H59.8672C59.8672 136.57 51.4122 136.57 59.8672 129.11Z" fill="url(#paint7_linear_14352_348907)"/>
+<path d="M153.37 48.5381C157.444 45.9293 161.327 48.5386 158.841 53.0146L128.999 111.703H182.216C182.216 111.703 190.671 111.703 182.216 118.666L90.206 199.734L89.9043 199.984C83.6025 205.11 79.3339 202.089 83.7402 193.766L112.587 136.57H59.8672L59.5205 136.556C58.0447 136.456 52.6656 135.667 59.4834 129.454L59.8672 129.11L153.37 48.5381ZM157.358 49.7138C157.097 49.5162 156.108 49.2016 154.55 50.1601L61.1728 130.625C59.1363 132.425 58.3889 133.553 58.1709 134.13C58.1586 134.162 58.1504 134.192 58.1425 134.217C58.3059 134.302 58.5992 134.409 59.0254 134.484C59.2691 134.527 59.4939 134.55 59.6562 134.561C59.7358 134.566 59.7973 134.568 59.8349 134.569C59.8537 134.57 59.8664 134.57 59.872 134.57H115.835L85.5263 194.667L85.5166 194.685L85.5078 194.702C84.4623 196.677 84.0261 198.177 83.9463 199.191C83.907 199.691 83.9586 200.015 84.0185 200.202C84.0743 200.376 84.1322 200.421 84.1367 200.425C84.1439 200.431 84.1966 200.473 84.3623 200.492C84.5453 200.513 84.8502 200.5 85.292 200.375C86.1886 200.12 87.4319 199.461 88.914 198.207L180.894 117.165L180.919 117.143L180.944 117.122C182.863 115.542 183.621 114.527 183.878 113.995C183.7 113.924 183.434 113.843 183.08 113.785C182.831 113.744 182.602 113.722 182.436 113.712C182.355 113.707 182.291 113.704 182.252 113.703H125.738L157.058 52.1084L157.074 52.0752L157.092 52.0429C157.573 51.1768 157.647 50.5775 157.616 50.2461C157.588 49.9474 157.477 49.8036 157.358 49.7138Z" fill="white"/>
+<defs>
+<linearGradient id="paint0_linear_14352_348907" x1="125.006" y1="0" x2="125.006" y2="250.003" gradientUnits="userSpaceOnUse">
+<stop stop-color="#F7BC1A"/>
+<stop offset="1" stop-color="#FF7700"/>
+</linearGradient>
+<linearGradient id="paint1_linear_14352_348907" x1="125.006" y1="0" x2="125.006" y2="250.003" gradientUnits="userSpaceOnUse">
+<stop stop-color="#F7BC1A"/>
+<stop offset="1" stop-color="#FF6A00"/>
+</linearGradient>
+<linearGradient id="paint2_linear_14352_348907" x1="125.006" y1="0" x2="125.006" y2="250.003" gradientUnits="userSpaceOnUse">
+<stop offset="0.725084" stop-color="#C94701" stop-opacity="0"/>
+<stop offset="1" stop-color="#C94701" stop-opacity="0.3"/>
+</linearGradient>
+<linearGradient id="paint3_linear_14352_348907" x1="125.006" y1="0.000349739" x2="125.006" y2="250.003" gradientUnits="userSpaceOnUse">
+<stop stop-color="#FFE091"/>
+<stop offset="1" stop-color="#FF9735"/>
+</linearGradient>
+<linearGradient id="paint4_linear_14352_348907" x1="125.006" y1="0.000349739" x2="125.006" y2="250.003" gradientUnits="userSpaceOnUse">
+<stop offset="0.85" stop-color="#FFA54D" stop-opacity="0"/>
+<stop offset="1" stop-color="#FFA54D"/>
+</linearGradient>
+<linearGradient id="paint5_linear_14352_348907" x1="125.006" y1="0.000349739" x2="125.006" y2="250.003" gradientUnits="userSpaceOnUse">
+<stop stop-color="#FFF3DA"/>
+<stop offset="0.15" stop-color="#FFF3DA" stop-opacity="0"/>
+</linearGradient>
+<linearGradient id="paint6_linear_14352_348907" x1="121.042" y1="57.5" x2="121.042" y2="212.5" gradientUnits="userSpaceOnUse">
+<stop stop-color="#F89A02"/>
+<stop offset="1" stop-color="#F56600"/>
+</linearGradient>
+<linearGradient id="paint7_linear_14352_348907" x1="121.042" y1="47.5" x2="121.042" y2="202.5" gradientUnits="userSpaceOnUse">
+<stop stop-color="white"/>
+<stop offset="1" stop-color="#FEEABD"/>
+</linearGradient>
+</defs>
+</svg>
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.