Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,14 @@ Future<void> main() async {
// is the only/primary API/repository for KDF
final KomodoDefiSdk komodoDefiSdk = await mm2.initialize();
final mm2Api = Mm2Api(mm2: mm2, sdk: komodoDefiSdk);
await AppBootstrapper.instance.ensureInitialized(komodoDefiSdk, mm2Api);
// Sparkline is dependent on Hive initialization, so we pass it on to the
// bootstrapper here
final sparklineRepository = SparklineRepository.defaultInstance();
await AppBootstrapper.instance.ensureInitialized(
komodoDefiSdk,
mm2Api,
sparklineRepository,
);

final coinsRepo = CoinsRepo(kdfSdk: komodoDefiSdk, mm2: mm2);
final walletsRepository = WalletsRepository(
Expand All @@ -77,13 +84,11 @@ Future<void> main() async {
path: '$assetsPath/translations',
child: MultiRepositoryProvider(
providers: [
RepositoryProvider(create: (_) => komodoDefiSdk),
RepositoryProvider(create: (_) => mm2Api),
RepositoryProvider(create: (_) => coinsRepo),
RepositoryProvider(create: (_) => walletsRepository),
// TODO: Refactor in SDK to avoid use of this global variable.
// This is necessary for now for CoinSparkline.
RepositoryProvider(create: (_) => sparklineRepository),
RepositoryProvider.value(value: komodoDefiSdk),
RepositoryProvider.value(value: mm2Api),
RepositoryProvider.value(value: coinsRepo),
RepositoryProvider.value(value: walletsRepository),
RepositoryProvider.value(value: sparklineRepository),
],
child: const MyApp(),
),
Expand Down
23 changes: 16 additions & 7 deletions lib/services/initializer/app_bootstrapper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ final class AppBootstrapper {

bool _isInitialized = false;

Future<void> ensureInitialized(KomodoDefiSdk kdfSdk, Mm2Api mm2Api) async {
Future<void> ensureInitialized(
KomodoDefiSdk kdfSdk,
Mm2Api mm2Api,
SparklineRepository sparklineRepository,
Comment thread
takenagain marked this conversation as resolved.
) async {
if (_isInitialized) return;

// Register core services with GetIt
Expand All @@ -22,8 +26,10 @@ final class AppBootstrapper {
log('AppBootstrapper: Log initialized in ${timer.elapsedMilliseconds}ms');
timer.reset();

await _warmUpInitializers().awaitAll();
log('AppBootstrapper: Warm-up initializers completed in ${timer.elapsedMilliseconds}ms');
await _warmUpInitializers(sparklineRepository).awaitAll();
log(
'AppBootstrapper: Warm-up initializers completed in ${timer.elapsedMilliseconds}ms',
);
timer.stop();

_isInitialized = true;
Expand All @@ -38,17 +44,20 @@ final class AppBootstrapper {

/// A list of futures that should be completed before the app starts
/// ([runApp]) which do not depend on each other.
List<Future<void>> _warmUpInitializers() {
List<Future<void>> _warmUpInitializers(
SparklineRepository sparklineRepository,
) {
return [
app_bloc_root.loadLibrary(),
packageInformation.init(),
EasyLocalization.ensureInitialized(),
CexMarketData.ensureInitialized(),
PlatformTuner.setWindowTitleAndSize(),
_initializeSettings(),
_initHive(isWeb: kIsWeb || kIsWasm, appFolder: appFolder).then(
(_) => sparklineRepository.init(),
),
_initHive(
isWeb: kIsWeb || kIsWasm,
appFolder: appFolder,
).then((_) => sparklineRepository.init()),
];
Comment thread
takenagain marked this conversation as resolved.
}

Expand Down
28 changes: 11 additions & 17 deletions lib/views/common/header/actions/header_actions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import 'package:komodo_ui_kit/komodo_ui_kit.dart';
import 'package:web_dex/app_config/app_config.dart';
import 'package:web_dex/bloc/coins_bloc/asset_coin_extension.dart';
import 'package:web_dex/bloc/coins_bloc/coins_bloc.dart';
import 'package:web_dex/bloc/cex_market_data/portfolio_growth/portfolio_growth_bloc.dart';
import 'package:web_dex/common/screen.dart';
import 'package:web_dex/generated/codegen_loader.g.dart';
import 'package:web_dex/model/coin.dart';
Expand All @@ -19,9 +18,7 @@ const EdgeInsets headerActionsPadding = EdgeInsets.fromLTRB(38, 18, 0, 0);
final _languageCodes = localeList.map((e) => e.languageCode).toList();
final _langCode2flags = {
for (var loc in _languageCodes)
loc: SvgPicture.asset(
'$assetsPath/flags/$loc.svg',
),
loc: SvgPicture.asset('$assetsPath/flags/$loc.svg'),
};
List<Widget>? getHeaderActions(BuildContext context) {
return <Widget>[
Expand All @@ -36,14 +33,12 @@ List<Widget>? getHeaderActions(BuildContext context) {
),
Padding(
padding: headerActionsPadding,
child: BlocBuilder<PortfolioGrowthBloc, PortfolioGrowthState>(
builder: (context, pgState) {
final coins = context.select<CoinsBloc, Iterable<Coin>>(
(bloc) => bloc.state.walletCoins.values,
child: BlocBuilder<CoinsBloc, CoinsState>(
builder: (context, state) {
final totalBalance = _getTotalBalance(
state.walletCoins.values,
context,
);
final totalBalance = pgState is PortfolioGrowthChartLoadSuccess
? pgState.totalBalance
: _getTotalBalance(coins, context);

return ActionTextButton(
text: LocaleKeys.balance.tr(),
Expand All @@ -53,17 +48,16 @@ List<Widget>? getHeaderActions(BuildContext context) {
},
),
),
const Padding(
padding: headerActionsPadding,
child: AccountSwitcher(),
),
const Padding(padding: headerActionsPadding, child: AccountSwitcher()),
if (!isWideScreen) const SizedBox(width: mainLayoutPadding),
];
}

double _getTotalBalance(Iterable<Coin> coins, BuildContext context) {
double total =
coins.fold(0, (prev, coin) => prev + (coin.usdBalance(context.sdk) ?? 0));
double total = coins.fold(
0,
(prev, coin) => prev + (coin.usdBalance(context.sdk) ?? 0),
);

if (total > 0.01) {
return total;
Expand Down
29 changes: 24 additions & 5 deletions lib/views/fiat/fiat_inputs.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import 'package:decimal/decimal.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:komodo_defi_sdk/komodo_defi_sdk.dart' show KomodoDefiSdk;
import 'package:komodo_defi_types/komodo_defi_types.dart'
show PubkeyInfo, AssetPubkeys;
import 'package:komodo_ui/komodo_ui.dart';
import 'package:komodo_ui/komodo_ui.dart' show Debouncer, SourceAddressField;
import 'package:komodo_ui_kit/komodo_ui_kit.dart';
import 'package:web_dex/bloc/fiat/models/fiat_price_info.dart';
import 'package:web_dex/bloc/fiat/models/i_currency.dart';
Expand Down Expand Up @@ -58,32 +59,41 @@ class FiatInputs extends StatefulWidget {

class FiatInputsState extends State<FiatInputs> {
TextEditingController fiatController = TextEditingController();
late final Debouncer _debouncer;
Comment thread
takenagain marked this conversation as resolved.
bool _hasUserInput = false;
Comment thread
takenagain marked this conversation as resolved.

@override
void dispose() {
fiatController.dispose();

_debouncer.dispose();
super.dispose();
}

@override
void initState() {
super.initState();
_debouncer = Debouncer(duration: const Duration(milliseconds: 300));
fiatController.text = widget.initialFiatAmount?.toString() ?? '';
}

@override
void didUpdateWidget(FiatInputs oldWidget) {
super.didUpdateWidget(oldWidget);

// Reset _hasUserInput flag when asset or fiat currency changes
if (oldWidget.selectedAsset != widget.selectedAsset ||
oldWidget.initialFiat != widget.initialFiat) {
_hasUserInput = false;
}

final Decimal? newFiatAmount = widget.initialFiatAmount;

// Convert the current text to Decimal for comparison
final Decimal currentFiatAmount =
Decimal.tryParse(fiatController.text) ?? Decimal.zero;

// Compare using Decimal values
if (newFiatAmount != currentFiatAmount) {
// Only update if user hasn't made changes or if amounts are different
if (!_hasUserInput && newFiatAmount != currentFiatAmount) {
final newFiatAmountText = newFiatAmount?.toString() ?? '';
Comment thread
takenagain marked this conversation as resolved.
fiatController
..text = newFiatAmountText
Expand All @@ -106,7 +116,16 @@ class FiatInputsState extends State<FiatInputs> {
}

void fiatAmountChanged(String? newValue) {
widget.onFiatAmountUpdate(newValue);
// track if user has made inputs to avoid overwriting them
// with stale bloc state updates (e.g. race condition)
_hasUserInput = true;
_debouncer.run(() {
if (mounted) {
widget.onFiatAmountUpdate(newValue);
Comment thread
takenagain marked this conversation as resolved.
// Reset flag after API call to allow future bloc state updates
_hasUserInput = false;
}
});
}

@override
Expand Down
2 changes: 1 addition & 1 deletion sdk
Submodule sdk updated from 170aab to 3f503d
Loading