make charts respect fiat api mode (#3678)

* make charts respect fiat api mode

* remove unused blocprovider

* https -> http

* https -> http
This commit is contained in:
malik1004x
2026-10-05 14:58:05 +02:00
committed by GitHub
parent bd8cc6901e
commit 1f1ba779f8
11 changed files with 151 additions and 98 deletions
+1 -1
View File
@@ -571,7 +571,7 @@ Future<void> setup({
(displayMode == BitcoinAmountDisplayMode.satoshiForLightning && lightningMode)));
});
getIt.registerLazySingleton<PriceStore>(() => PriceStore());
getIt.registerLazySingleton<PriceStore>(() => PriceStore(settingsStore: getIt.get<SettingsStore>()));
getIt.registerFactory<ChartsBloc>(
() => ChartsBloc(appStore: getIt.get<AppStore>(), priceStore: getIt.get<PriceStore>()));
@@ -22,7 +22,7 @@ class LatestPriceRequest {
"quote": to.apiString,
});
Uri get onionUri => Uri.https(priceApiHostOnion, uri.path, uri.queryParameters);
Uri get onionUri => Uri.http(priceApiHostOnion, uri.path, uri.queryParameters);
}
class PriceRequest {
@@ -49,7 +49,7 @@ class PriceRequest {
"base": to.apiString,
});
Uri get onionUri => Uri.https(priceApiHostOnion, uri.path, uri.queryParameters);
Uri get onionUri => Uri.http(priceApiHostOnion, uri.path, uri.queryParameters);
}
class PriceApiClient {
+13 -2
View File
@@ -1,6 +1,8 @@
import "package:cake_wallet/entities/fiat_api_mode.dart";
import "package:cake_wallet/new-ui/model/charts/price_api_client.dart";
import "package:cake_wallet/new-ui/model/charts/price_data.dart";
import "package:cake_wallet/new-ui/model/charts/util/chart_range.dart";
import "package:cake_wallet/store/settings_store.dart";
import "package:cw_core/currency.dart";
import "package:cw_core/utils/print_verbose.dart";
@@ -13,6 +15,7 @@ abstract class PriceSource {
Currency from,
Currency to,
Duration interval,
{required bool torOnly,}
);
}
@@ -30,6 +33,7 @@ class DatabasePriceSource extends PriceSource with UpdatablePriceSource {
Currency from,
Currency to,
Duration interval,
{required bool torOnly,}
) =>
PriceData.get(from, to, start, end);
@@ -49,13 +53,19 @@ class ApiPriceSource extends PriceSource {
Currency from,
Currency to,
Duration interval,
) =>
{required bool torOnly,}
) =>
PriceApiClient.getPrices(
torOnly: torOnly,
PriceRequest(beginTime: start, interval: interval, from: from, to: to),
);
}
class PriceStore {
const PriceStore({required this.settingsStore});
final SettingsStore settingsStore;
static const priceSources = [
// TODO InMemoryPriceSource() - easily implementable w this pattern but idk if we need to optimize this that much
DatabasePriceSource(),
@@ -76,7 +86,8 @@ class PriceStore {
final alignedStart = start;
for (final source in priceSources) {
final sourceData = await source.get(start!, end, from, to, range.dataPrecision);
final sourceData = await source.get(start!, end, from, to, range.dataPrecision,
torOnly: settingsStore.fiatApiMode == FiatApiMode.torOnly,);
data.addAll(sourceData);
start = _firstUnavailablePrice(data.toList(), range.dataPrecision, start, end);
if (start == null) {
+95 -74
View File
@@ -1,3 +1,4 @@
import "package:cake_wallet/generated/i18n.dart";
import "package:cake_wallet/new-ui/page_open_listener.dart";
import "package:cake_wallet/new-ui/viewmodels/charts/charts_bloc.dart";
import "package:cake_wallet/new-ui/widgets/charts_page/asset_grid.dart";
@@ -20,84 +21,104 @@ class ChartsPage extends StatelessWidget implements PageOpenListener {
}
@override
Widget build(BuildContext context) => BlocProvider(
create: (context) => chartsBloc,
child: BlocBuilder<ChartsBloc, ChartsState>(
builder: (context, state) {
if (state is ChartsInitial) {
return const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
spacing: 24,
children: [
CakeImageWidget(
width: 36,
height: 36,
imageUrl: "assets/new-ui/navbar/charts.svg",
),
CupertinoActivityIndicator(),
if (kDebugMode)
Text(
"devs: if this doesn't go away in a few seconds, either your device is painfully slow or the db is messed up",
),
],
),
);
}
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Theme.of(context).colorScheme.surface,
Theme.of(context).colorScheme.surfaceDim,
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
),
child: CustomScrollView(
physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
slivers: [
SliverPadding(
padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
sliver: CupertinoSliverRefreshControl(
refreshTriggerPullDistance: 160,
refreshIndicatorExtent: 90,
onRefresh: () async => chartsBloc.add(PageRefreshed()),
),
Widget build(BuildContext context) => BlocBuilder<ChartsBloc, ChartsState>(
bloc: chartsBloc,
builder: (context, state) {
if (state is ChartsInitial) {
return const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
spacing: 24,
children: [
CakeImageWidget(
width: 36,
height: 36,
imageUrl: "assets/new-ui/navbar/charts.svg",
),
SliverToBoxAdapter(
child: SafeArea(
child: Column(
spacing: 24,
children: [
if (state is ChartsStateWithData)
ChartHeader(
currency: state.pinnedCurrency,
chartHeight: 100,
chartPadding: 22,
centered: false,
favorite: true,
),
const Padding(
padding: EdgeInsets.symmetric(horizontal: 18),
child: Column(
spacing: 24,
children: [ChartsAssetGridHeader(), ChartsAssetGrid()],
),
),
const SizedBox(
height: 96,
),
],
),
CupertinoActivityIndicator(),
if (kDebugMode)
Text(
"devs: if this doesn't go away in a few seconds, either your device is painfully slow or the db is messed up",
),
),
],
),
);
},
),
}
if (state is ChartsDisabled) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
spacing: 12,
children: [
CakeImageWidget(
width: 36,
height: 36,
imageUrl: "assets/new-ui/navbar/charts.svg",
),
Text(
S.of(context).charts_unavailable,
style: const TextStyle(fontSize: 24, fontWeight: FontWeight.w600),
),
Text(S.of(context).charts_unavailable_desc),
],
),
);
}
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Theme.of(context).colorScheme.surface,
Theme.of(context).colorScheme.surfaceDim,
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
),
child: CustomScrollView(
physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
slivers: [
SliverPadding(
padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
sliver: CupertinoSliverRefreshControl(
refreshTriggerPullDistance: 160,
refreshIndicatorExtent: 90,
onRefresh: () async => chartsBloc.add(PageRefreshed()),
),
),
SliverToBoxAdapter(
child: SafeArea(
child: Column(
spacing: 24,
children: [
if (state is ChartsStateWithData)
ChartHeader(
bloc: chartsBloc,
currency: state.pinnedCurrency,
chartHeight: 100,
chartPadding: 22,
centered: false,
favorite: true,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 18),
child: Column(
spacing: 24,
children: [ChartsAssetGridHeader(bloc: chartsBloc), ChartsAssetGrid(bloc: chartsBloc)],
),
),
const SizedBox(
height: 96,
),
],
),
),
),
],
),
);
},
);
}
@@ -3,6 +3,7 @@ import "dart:async";
import "package:bloc/bloc.dart";
import "package:bloc_concurrency/bloc_concurrency.dart";
import "package:cake_wallet/core/utilities.dart";
import "package:cake_wallet/entities/fiat_api_mode.dart";
import "package:cake_wallet/entities/fiat_currency.dart";
import "package:cake_wallet/new-ui/model/charts/charts_asset.dart";
import "package:cake_wallet/new-ui/model/charts/price_data.dart";
@@ -13,7 +14,6 @@ import "package:cake_wallet/new-ui/model/charts/util/price_change_direction.dart
import "package:cake_wallet/new-ui/model/charts/util/price_data_sort_criteria.dart";
import "package:cake_wallet/store/app_store.dart";
import "package:cw_core/amount/money.dart";
import "package:cw_core/crypto_amount_format.dart";
import "package:cw_core/crypto_currency.dart";
import "package:flutter/foundation.dart";
@@ -30,17 +30,23 @@ class ChartsBloc extends Bloc<ChartsEvent, ChartsState> {
on<CurrencyPinned>(_onCurrencyPinned, transformer: sequential());
on<PageRefreshed>(_onPageRefreshed, transformer: sequential());
on<PageLoadStarted>(_onPageLoadStarted, transformer: restartable());
on<Init>(_init);
on<Init>(_init, transformer: sequential());
}
final PriceStore priceStore;
final AppStore appStore;
Future<void> _init(Init event, Emitter<ChartsState> emit) async {
if (state is! ChartsInitial) {
if(appStore.settingsStore.fiatApiMode == FiatApiMode.disabled) {
emit(const ChartsDisabled());
return;
}
if (state is! ChartsInitial) {
emit(const ChartsInitial());
}
final assets = await ChartsAsset.get();
if (assets.isEmpty) {
@@ -9,6 +9,10 @@ final class ChartsInitial extends ChartsState {
const ChartsInitial();
}
final class ChartsDisabled extends ChartsState {
const ChartsDisabled();
}
abstract final class ChartsStateWithData extends ChartsState {
const ChartsStateWithData({
required this.pinnedCurrency,
+11 -5
View File
@@ -17,10 +17,13 @@ import "package:flutter/services.dart";
import "package:flutter_bloc/flutter_bloc.dart";
class ChartsAssetGrid extends StatelessWidget {
const ChartsAssetGrid({super.key});
const ChartsAssetGrid({required this.bloc, super.key});
final ChartsBloc bloc;
@override
Widget build(BuildContext context) => BlocBuilder<ChartsBloc, ChartsState>(
bloc: bloc,
builder: (context, state) {
if (state is ChartsStateWithData) {
final currencies = state.currencies;
@@ -36,6 +39,7 @@ class ChartsAssetGrid extends StatelessWidget {
itemBuilder: (context, index) {
final curr = currencies[index];
return ChartsAssetCard(
bloc: bloc,
currency: curr,
price: state.priceFor(curr)?.toStringWithPrecision(fractionalDigits: 2) ?? "...",
ticker: state.fiatTicker,
@@ -53,7 +57,7 @@ class ChartsAssetGrid extends StatelessWidget {
class ChartsAssetCard extends StatelessWidget {
const ChartsAssetCard(
{super.key,
{required this.bloc, super.key,
required this.currency,
required this.price,
required this.ticker,
@@ -67,6 +71,7 @@ class ChartsAssetCard extends StatelessWidget {
final PriceChangeData? changeData;
final bool favorite;
final bool isSingleCurrency;
final ChartsBloc bloc;
String get displayPrice {
try {
@@ -88,7 +93,7 @@ class ChartsAssetCard extends StatelessWidget {
label: S.of(context).favorite,
iconPath: "assets/new-ui/favorite.svg",
onSelected: () {
context.read<ChartsBloc>().add(CurrencyPinned(currency: currency));
bloc.add(CurrencyPinned(currency: currency));
Navigator.of(context).pop();
},
color: favorite ? Theme.of(context).colorScheme.error : null,),
@@ -97,7 +102,7 @@ class ChartsAssetCard extends StatelessWidget {
iconPath: "assets/new-ui/address_hide.svg",
onSelected: () {
if (!isSingleCurrency) {
context.read<ChartsBloc>().add(CurrencyRemoved(currency: currency));
bloc.add(CurrencyRemoved(currency: currency));
Navigator.of(context).pop();
}
},
@@ -112,11 +117,12 @@ class ChartsAssetCard extends StatelessWidget {
isScrollControlled: true,
context: context,
builder: (context) => ChartModal(
bloc: bloc,
currency: currency,
isFavorite: favorite,
),);
if (res != null && res is bool && res) {
context.read<ChartsBloc>().add(CurrencyPinned(currency: currency));
bloc.add(CurrencyPinned(currency: currency));
}
},
child: Container(
@@ -12,13 +12,15 @@ import "package:flutter_bloc/flutter_bloc.dart";
class ChartsAssetGridHeader extends StatelessWidget {
const ChartsAssetGridHeader({
super.key,
required this.bloc, super.key,
});
final ChartsBloc bloc;
@override
Widget build(BuildContext context) => BlocBuilder<ChartsBloc, ChartsState>(
bloc: bloc,
builder: (context, state) {
final bloc = context.read<ChartsBloc>();
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
@@ -15,7 +15,7 @@ import "package:intl/intl.dart";
class ChartHeader extends StatefulWidget {
const ChartHeader({
super.key,
required this.bloc, super.key,
required this.currency,
required this.chartHeight,
required this.chartPadding,
@@ -28,6 +28,7 @@ class ChartHeader extends StatefulWidget {
final double chartPadding;
final bool centered;
final bool favorite;
final ChartsBloc bloc;
@override
State<ChartHeader> createState() => _ChartHeaderState();
@@ -39,6 +40,7 @@ class _ChartHeaderState extends State<ChartHeader> {
@override
Widget build(BuildContext context) => BlocBuilder<ChartsBloc, ChartsState>(
bloc: widget.bloc,
builder: (context, state) {
if (state case final ChartsStateWithData s) {
return Column(
@@ -149,7 +151,7 @@ class _ChartHeaderState extends State<ChartHeader> {
ChartRangeSelector(
selectedRange: s.range,
onRangeSelected: (range) =>
context.read<ChartsBloc>().add(RangeChanged(newRange: range)),
widget.bloc.add(RangeChanged(newRange: range)),
),
],
),
@@ -19,15 +19,14 @@ import "package:flutter_bloc/flutter_bloc.dart";
import "package:modal_bottom_sheet/modal_bottom_sheet.dart";
class ChartModal extends StatelessWidget {
const ChartModal({required this.currency, required this.isFavorite, super.key});
const ChartModal({required this.bloc, required this.currency, required this.isFavorite, super.key});
final CryptoCurrency currency;
final bool isFavorite;
final ChartsBloc bloc;
@override
Widget build(BuildContext context) => BlocProvider(
create: (context) => getIt.get<ChartsBloc>()..add(Init()),
child: Container(
Widget build(BuildContext context) => Container(
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface,
borderRadius: const BorderRadius.vertical(top: Radius.circular(18)),
@@ -43,6 +42,7 @@ class ChartModal extends StatelessWidget {
padding: const EdgeInsets.only(top: 18, left: 18),
),
ChartHeader(
bloc: bloc,
currency: currency,
chartHeight: 220,
chartPadding: 32,
@@ -135,9 +135,8 @@ class ChartModal extends StatelessWidget {
],
),
),
),
);
);
void openBuySellPage(BuildContext context, BuySellPageMode mode) {
Navigator.of(context).pop();
final page = getIt.get<NewBuySellAmountPage>(
+2
View File
@@ -210,6 +210,8 @@
"change_wallet_alert_content": "Do you want to change current wallet to ${wallet_name}?",
"change_wallet_alert_title": "Change current wallet",
"charts": "Charts",
"charts_unavailable": "Charts unavailable",
"charts_unavailable_desc": "Please enable the Fiat API in Settings.",
"check_receiver_forms": "Please, check receiver forms",
"choose_a_payment_method": "Choose a payment method",
"choose_a_provider": "Choose a provider",