-
Notifications
You must be signed in to change notification settings - Fork 77
Expand file tree
/
Copy pathbitcoin_price_bloc.dart
More file actions
137 lines (120 loc) · 4.93 KB
/
Copy pathbitcoin_price_bloc.dart
File metadata and controls
137 lines (120 loc) · 4.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import 'dart:async';
import 'package:bb_mobile/core/exchange/domain/usecases/convert_sats_to_currency_amount_usecase.dart';
import 'package:bb_mobile/core/exchange/domain/usecases/get_available_currencies_usecase.dart';
import 'package:bb_mobile/core/settings/domain/get_settings_usecase.dart';
import 'package:bb_mobile/core/settings/domain/settings_entity.dart';
import 'package:bb_mobile/core/settings/domain/watch_currency_changes_usecase.dart';
import 'package:bb_mobile/core/utils/amount_conversions.dart';
import 'package:bb_mobile/core/utils/logger.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:intl/intl.dart';
part 'bitcoin_price_bloc.freezed.dart';
part 'bitcoin_price_event.dart';
part 'bitcoin_price_state.dart';
class BitcoinPriceBloc extends Bloc<BitcoinPriceEvent, BitcoinPriceState> {
BitcoinPriceBloc({
required GetAvailableCurrenciesUsecase getAvailableCurrenciesUsecase,
required GetSettingsUsecase getSettingsUsecase,
required ConvertSatsToCurrencyAmountUsecase
convertSatsToCurrencyAmountUsecase,
required WatchCurrencyChangesUsecase watchCurrencyChangesUsecase,
}) : _getAvailableCurrenciesUsecase = getAvailableCurrenciesUsecase,
_getSettingsUsecase = getSettingsUsecase,
_convertSatsToCurrencyAmountUsecase = convertSatsToCurrencyAmountUsecase,
_watchCurrencyChangesUsecase = watchCurrencyChangesUsecase,
super(const BitcoinPriceState()) {
on<BitcoinPriceStarted>(_onStarted);
on<BitcoinPriceFetched>(_onFetched);
on<BitcoinPriceCurrencyChanged>(_onCurrencyChanged);
// Watch for currency changes and emit a new state when the currency changes
_currencyChangeSubscription = _watchCurrencyChangesUsecase.execute().listen(
(currencyCode) {
log.info('Currency changed to $currencyCode');
add(BitcoinPriceCurrencyChanged(currencyCode: currencyCode));
},
);
}
final GetAvailableCurrenciesUsecase _getAvailableCurrenciesUsecase;
final GetSettingsUsecase _getSettingsUsecase;
final ConvertSatsToCurrencyAmountUsecase _convertSatsToCurrencyAmountUsecase;
final WatchCurrencyChangesUsecase _watchCurrencyChangesUsecase;
late final StreamSubscription<String> _currencyChangeSubscription;
@override
Future<void> close() async {
await _currencyChangeSubscription.cancel();
return super.close();
}
Future<void> _onStarted(
BitcoinPriceStarted event,
Emitter<BitcoinPriceState> emit,
) async {
log.info('FiatCurrenciesStarted');
try {
final settings = await _getSettingsUsecase.execute();
final currency = event.currency ?? settings.currencyCode;
final availableCurrencies = await _getAvailableCurrenciesUsecase
.execute();
final price = await _convertSatsToCurrencyAmountUsecase.execute(
currencyCode: currency,
);
emit(
BitcoinPriceState(
currency: currency,
availableCurrencies: availableCurrencies,
bitcoinPrice: price,
startupFailed: false,
error: null,
),
);
} catch (e) {
log.severe(e.toString());
emit(state.copyWith(error: e, startupFailed: true));
}
}
Future<void> _onFetched(
BitcoinPriceFetched event,
Emitter<BitcoinPriceState> emit,
) async {
log.info('BitcoinPriceFetched');
try {
final currency = state.currency;
if (currency != null) {
final price = await _convertSatsToCurrencyAmountUsecase.execute(
currencyCode: currency,
);
emit(state.copyWith(bitcoinPrice: price));
}
} catch (e) {
log.severe(e.toString());
// TODO: would it make sense to not emit a failure state here, but keep the
// previous success state as to be able to show an exchange rate allthough
// not the most recent one? If that makes sense, we can add the error directly
// to the success state. So the UI can show the exchange rate, but also show
// that it might not be the most recent one.
// (Adding a fetch and rate timestamp to the success can also help)
emit(state.copyWith(error: e));
}
}
Future<void> _onCurrencyChanged(
BitcoinPriceCurrencyChanged event,
Emitter<BitcoinPriceState> emit,
) async {
log.info('BitcoinPriceCurrencyChanged to ${event.currencyCode}');
try {
// The state should be in the success state, otherwise try to start the bloc
// again with the new currency in the event.
// final successState = state as BitcoinPriceSuccess;
final currency = event.currencyCode;
// Get the exchange rate for the new currency
final price = await _convertSatsToCurrencyAmountUsecase.execute(
currencyCode: currency,
);
emit(state.copyWith(currency: currency, bitcoinPrice: price));
} catch (e) {
log.severe(e.toString());
emit(state.copyWith(error: e));
}
}
}