add loading screen if not exchange data cache exists while waiting for it to be populated for the first time. Added checks for incognito mode

This commit is contained in:
julian 2023-02-08 08:43:42 -06:00
parent b9d006b6ea
commit 8206972309
5 changed files with 468 additions and 268 deletions

View file

@ -17,6 +17,7 @@ import 'package:hive_flutter/hive_flutter.dart';
import 'package:isar/isar.dart'; import 'package:isar/isar.dart';
import 'package:keyboard_dismisser/keyboard_dismisser.dart'; import 'package:keyboard_dismisser/keyboard_dismisser.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:stackwallet/db/main_db.dart';
import 'package:stackwallet/hive/db.dart'; import 'package:stackwallet/hive/db.dart';
import 'package:stackwallet/models/exchange/change_now/exchange_transaction.dart'; import 'package:stackwallet/models/exchange/change_now/exchange_transaction.dart';
import 'package:stackwallet/models/exchange/change_now/exchange_transaction_status.dart'; import 'package:stackwallet/models/exchange/change_now/exchange_transaction_status.dart';
@ -65,8 +66,6 @@ import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/utilities/util.dart';
import 'package:window_size/window_size.dart'; import 'package:window_size/window_size.dart';
import 'db/main_db.dart';
final openedFromSWBFileStringStateProvider = final openedFromSWBFileStringStateProvider =
StateProvider<String?>((ref) => null); StateProvider<String?>((ref) => null);
@ -290,10 +289,6 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
// TODO: this should probably run unawaited. Keep commented out for now as proper community nodes ui hasn't been implemented yet // TODO: this should probably run unawaited. Keep commented out for now as proper community nodes ui hasn't been implemented yet
// unawaited(_nodeService.updateCommunityNodes()); // unawaited(_nodeService.updateCommunityNodes());
print("================================================");
print("${ref.read(prefsChangeNotifierProvider).externalCalls}");
print("${await ref.read(prefsChangeNotifierProvider).isExternalCallsSet()}");
print("================================================");
// run without awaiting // run without awaiting
if (ref.read(prefsChangeNotifierProvider).externalCalls && if (ref.read(prefsChangeNotifierProvider).externalCalls &&
await ref.read(prefsChangeNotifierProvider).isExternalCallsSet()) { await ref.read(prefsChangeNotifierProvider).isExternalCallsSet()) {

View file

@ -8,9 +8,12 @@ import 'package:stackwallet/pages/exchange_view/exchange_form.dart';
import 'package:stackwallet/pages/exchange_view/trade_details_view.dart'; import 'package:stackwallet/pages/exchange_view/trade_details_view.dart';
import 'package:stackwallet/providers/global/trades_service_provider.dart'; import 'package:stackwallet/providers/global/trades_service_provider.dart';
import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart';
import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_loading_overlay.dart';
import 'package:stackwallet/widgets/trade_card.dart'; import 'package:stackwallet/widgets/trade_card.dart';
import 'package:tuple/tuple.dart'; import 'package:tuple/tuple.dart';
@ -24,8 +27,38 @@ class ExchangeView extends ConsumerStatefulWidget {
} }
class _ExchangeViewState extends ConsumerState<ExchangeView> { class _ExchangeViewState extends ConsumerState<ExchangeView> {
bool _initialCachePopulationUnderway = false;
@override @override
void initState() { void initState() {
if (!ref.read(prefsChangeNotifierProvider).externalCalls) {
if (ExchangeDataLoadingService.currentCacheVersion <
ExchangeDataLoadingService.cacheVersion) {
_initialCachePopulationUnderway = true;
ExchangeDataLoadingService.instance.onLoadingComplete = () {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
setState(() {
_initialCachePopulationUnderway = false;
});
});
};
}
ExchangeDataLoadingService.instance
.init()
.then((_) => ExchangeDataLoadingService.instance.loadAll());
} else if (ExchangeDataLoadingService.instance.isLoading &&
ExchangeDataLoadingService.currentCacheVersion <
ExchangeDataLoadingService.cacheVersion) {
_initialCachePopulationUnderway = true;
ExchangeDataLoadingService.instance.onLoadingComplete = () {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
setState(() {
_initialCachePopulationUnderway = false;
});
});
};
}
super.initState(); super.initState();
} }
@ -38,154 +71,176 @@ class _ExchangeViewState extends ConsumerState<ExchangeView> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
debugPrint("BUILD: $runtimeType"); debugPrint("BUILD: $runtimeType");
return SafeArea( return ConditionalParent(
child: NestedScrollView( condition: _initialCachePopulationUnderway,
floatHeaderSlivers: true, builder: (child) {
headerSliverBuilder: (context, innerBoxIsScrolled) { return Stack(
return [ children: [
SliverOverlapAbsorber( child,
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), Material(
sliver: const SliverToBoxAdapter( color: Theme.of(context)
child: Padding( .extension<StackColors>()!
padding: EdgeInsets.only( .overlay
left: 16, .withOpacity(0.6),
right: 16, child: const CustomLoadingOverlay(
top: 16, message: "Updating exchange data",
), subMessage: "This could take a few minutes",
child: ExchangeForm(), eventBus: null,
),
), ),
) )
]; ],
}, );
body: Builder( },
builder: (buildContext) { child: SafeArea(
final trades = ref child: NestedScrollView(
.watch(tradesServiceProvider.select((value) => value.trades)); floatHeaderSlivers: true,
final tradeCount = trades.length; headerSliverBuilder: (context, innerBoxIsScrolled) {
final hasHistory = tradeCount > 0; return [
SliverOverlapAbsorber(
return Padding( handle:
padding: const EdgeInsets.symmetric(horizontal: 12), NestedScrollView.sliverOverlapAbsorberHandleFor(context),
child: CustomScrollView( sliver: const SliverToBoxAdapter(
slivers: [ child: Padding(
SliverOverlapInjector( padding: EdgeInsets.only(
handle: NestedScrollView.sliverOverlapAbsorberHandleFor( left: 16,
buildContext, right: 16,
top: 16,
), ),
child: ExchangeForm(),
), ),
SliverToBoxAdapter( ),
child: Padding( )
padding: const EdgeInsets.symmetric(horizontal: 4), ];
child: Column( },
crossAxisAlignment: CrossAxisAlignment.stretch, body: Builder(
children: [ builder: (buildContext) {
const SizedBox( final trades = ref
height: 12, .watch(tradesServiceProvider.select((value) => value.trades));
), final tradeCount = trades.length;
Text( final hasHistory = tradeCount > 0;
"Trades",
style: STextStyles.itemSubtitle(context).copyWith( return Padding(
color: Theme.of(context) padding: const EdgeInsets.symmetric(horizontal: 12),
.extension<StackColors>()! child: CustomScrollView(
.textDark3, slivers: [
), SliverOverlapInjector(
), handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
const SizedBox( buildContext,
height: 12,
),
],
), ),
), ),
),
if (hasHistory)
SliverList(
delegate: SliverChildBuilderDelegate((context, index) {
return Padding(
padding: const EdgeInsets.all(4),
child: TradeCard(
key: Key("tradeCard_${trades[index].uuid}"),
trade: trades[index],
onTap: () async {
final String tradeId = trades[index].tradeId;
final lookup = ref
.read(tradeSentFromStackLookupProvider)
.all;
//todo: check if print needed
// debugPrint("ALL: $lookup");
final String? txid = ref
.read(tradeSentFromStackLookupProvider)
.getTxidForTradeId(tradeId);
final List<String>? walletIds = ref
.read(tradeSentFromStackLookupProvider)
.getWalletIdsForTradeId(tradeId);
if (txid != null &&
walletIds != null &&
walletIds.isNotEmpty) {
final manager = ref
.read(walletsChangeNotifierProvider)
.getManager(walletIds.first);
//todo: check if print needed
// debugPrint("name: ${manager.walletName}");
final tx = await MainDB.instance
.getTransactions(walletIds.first)
.filter()
.txidEqualTo(txid)
.findFirst();
if (mounted) {
unawaited(Navigator.of(context).pushNamed(
TradeDetailsView.routeName,
arguments: Tuple4(tradeId, tx,
walletIds.first, manager.walletName),
));
}
} else {
unawaited(Navigator.of(context).pushNamed(
TradeDetailsView.routeName,
arguments: Tuple4(
tradeId, null, walletIds?.first, null),
));
}
},
),
);
}, childCount: tradeCount),
),
if (!hasHistory)
SliverToBoxAdapter( SliverToBoxAdapter(
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 4), padding: const EdgeInsets.symmetric(horizontal: 4),
child: Container( child: Column(
decoration: BoxDecoration( crossAxisAlignment: CrossAxisAlignment.stretch,
color: Theme.of(context) children: [
.extension<StackColors>()! const SizedBox(
.popupBG, height: 12,
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
), ),
), Text(
child: Padding( "Trades",
padding: const EdgeInsets.all(12), style: STextStyles.itemSubtitle(context).copyWith(
child: Text( color: Theme.of(context)
"Trades will appear here", .extension<StackColors>()!
textAlign: TextAlign.center, .textDark3,
style: STextStyles.itemSubtitle(context), ),
),
const SizedBox(
height: 12,
),
],
),
),
),
if (hasHistory)
SliverList(
delegate: SliverChildBuilderDelegate((context, index) {
return Padding(
padding: const EdgeInsets.all(4),
child: TradeCard(
key: Key("tradeCard_${trades[index].uuid}"),
trade: trades[index],
onTap: () async {
final String tradeId = trades[index].tradeId;
final lookup = ref
.read(tradeSentFromStackLookupProvider)
.all;
//todo: check if print needed
// debugPrint("ALL: $lookup");
final String? txid = ref
.read(tradeSentFromStackLookupProvider)
.getTxidForTradeId(tradeId);
final List<String>? walletIds = ref
.read(tradeSentFromStackLookupProvider)
.getWalletIdsForTradeId(tradeId);
if (txid != null &&
walletIds != null &&
walletIds.isNotEmpty) {
final manager = ref
.read(walletsChangeNotifierProvider)
.getManager(walletIds.first);
//todo: check if print needed
// debugPrint("name: ${manager.walletName}");
final tx = await MainDB.instance
.getTransactions(walletIds.first)
.filter()
.txidEqualTo(txid)
.findFirst();
if (mounted) {
unawaited(Navigator.of(context).pushNamed(
TradeDetailsView.routeName,
arguments: Tuple4(tradeId, tx,
walletIds.first, manager.walletName),
));
}
} else {
unawaited(Navigator.of(context).pushNamed(
TradeDetailsView.routeName,
arguments: Tuple4(
tradeId, null, walletIds?.first, null),
));
}
},
),
);
}, childCount: tradeCount),
),
if (!hasHistory)
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
child: Container(
decoration: BoxDecoration(
color: Theme.of(context)
.extension<StackColors>()!
.popupBG,
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
child: Padding(
padding: const EdgeInsets.all(12),
child: Text(
"Trades will appear here",
textAlign: TextAlign.center,
style: STextStyles.itemSubtitle(context),
),
), ),
), ),
), ),
), ),
), ],
], ),
), );
); },
}, ),
), ),
), ),
); );

View file

@ -4,11 +4,15 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/pages/exchange_view/exchange_form.dart'; import 'package:stackwallet/pages/exchange_view/exchange_form.dart';
import 'package:stackwallet/pages/exchange_view/sub_widgets/step_row.dart'; import 'package:stackwallet/pages/exchange_view/sub_widgets/step_row.dart';
import 'package:stackwallet/providers/global/prefs_provider.dart';
import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/background.dart'; import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/custom_loading_overlay.dart';
class WalletInitiatedExchangeView extends ConsumerStatefulWidget { class WalletInitiatedExchangeView extends ConsumerStatefulWidget {
const WalletInitiatedExchangeView({ const WalletInitiatedExchangeView({
@ -32,10 +36,41 @@ class _WalletInitiatedExchangeViewState
late final String walletId; late final String walletId;
late final Coin coin; late final Coin coin;
bool _initialCachePopulationUnderway = false;
@override @override
void initState() { void initState() {
walletId = widget.walletId; walletId = widget.walletId;
coin = widget.coin; coin = widget.coin;
if (!ref.read(prefsChangeNotifierProvider).externalCalls) {
if (ExchangeDataLoadingService.currentCacheVersion <
ExchangeDataLoadingService.cacheVersion) {
_initialCachePopulationUnderway = true;
ExchangeDataLoadingService.instance.onLoadingComplete = () {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
setState(() {
_initialCachePopulationUnderway = false;
});
});
};
}
ExchangeDataLoadingService.instance
.init()
.then((_) => ExchangeDataLoadingService.instance.loadAll());
} else if (ExchangeDataLoadingService.instance.isLoading &&
ExchangeDataLoadingService.currentCacheVersion <
ExchangeDataLoadingService.cacheVersion) {
_initialCachePopulationUnderway = true;
ExchangeDataLoadingService.instance.onLoadingComplete = () {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
setState(() {
_initialCachePopulationUnderway = false;
});
});
};
}
super.initState(); super.initState();
} }
@ -48,76 +83,98 @@ class _WalletInitiatedExchangeViewState
Widget build(BuildContext context) { Widget build(BuildContext context) {
debugPrint("BUILD: $runtimeType"); debugPrint("BUILD: $runtimeType");
return Background( return ConditionalParent(
child: Scaffold( condition: _initialCachePopulationUnderway,
backgroundColor: Theme.of(context).extension<StackColors>()!.background, builder: (child) {
appBar: AppBar( return Stack(
leading: AppBarBackButton( children: [
onPressed: () async { child,
if (FocusScope.of(context).hasFocus) { Material(
FocusScope.of(context).unfocus(); color: Theme.of(context)
await Future<void>.delayed(const Duration(milliseconds: 75)); .extension<StackColors>()!
} .overlay
if (mounted) { .withOpacity(0.6),
Navigator.of(context).pop(); child: const CustomLoadingOverlay(
} message: "Updating exchange data",
}, subMessage: "This could take a few minutes",
eventBus: null,
),
)
],
);
},
child: Background(
child: Scaffold(
backgroundColor:
Theme.of(context).extension<StackColors>()!.background,
appBar: AppBar(
leading: AppBarBackButton(
onPressed: () async {
if (FocusScope.of(context).hasFocus) {
FocusScope.of(context).unfocus();
await Future<void>.delayed(const Duration(milliseconds: 75));
}
if (mounted) {
Navigator.of(context).pop();
}
},
),
title: Text(
"Exchange",
style: STextStyles.navBarTitle(context),
),
), ),
title: Text( body: LayoutBuilder(
"Exchange", builder: (context, constraints) {
style: STextStyles.navBarTitle(context), final width = MediaQuery.of(context).size.width - 32;
), return Padding(
), padding: const EdgeInsets.all(12),
body: LayoutBuilder( child: SingleChildScrollView(
builder: (context, constraints) { child: ConstrainedBox(
final width = MediaQuery.of(context).size.width - 32; constraints: BoxConstraints(
return Padding( minHeight: constraints.maxHeight - 24,
padding: const EdgeInsets.all(12), ),
child: SingleChildScrollView( child: IntrinsicHeight(
child: ConstrainedBox( child: Padding(
constraints: BoxConstraints( padding: const EdgeInsets.all(4),
minHeight: constraints.maxHeight - 24, child: Column(
), crossAxisAlignment: CrossAxisAlignment.stretch,
child: IntrinsicHeight( children: [
child: Padding( StepRow(
padding: const EdgeInsets.all(4), count: 4,
child: Column( current: 0,
crossAxisAlignment: CrossAxisAlignment.stretch, width: width,
children: [ ),
StepRow( const SizedBox(
count: 4, height: 14,
current: 0, ),
width: width, Text(
), "Exchange amount",
const SizedBox( style: STextStyles.pageTitleH1(context),
height: 14, ),
), const SizedBox(
Text( height: 8,
"Exchange amount", ),
style: STextStyles.pageTitleH1(context), Text(
), "Network fees and other exchange charges are included in the rate.",
const SizedBox( style: STextStyles.itemSubtitle(context),
height: 8, ),
), const SizedBox(
Text( height: 24,
"Network fees and other exchange charges are included in the rate.", ),
style: STextStyles.itemSubtitle(context), ExchangeForm(
), walletId: walletId,
const SizedBox( coin: coin,
height: 24, ),
), ],
ExchangeForm( ),
walletId: walletId,
coin: coin,
),
],
), ),
), ),
), ),
), ),
), );
); },
}, ),
), ),
), ),
); );

View file

@ -1,79 +1,142 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/pages/exchange_view/exchange_form.dart'; import 'package:stackwallet/pages/exchange_view/exchange_form.dart';
import 'package:stackwallet/pages_desktop_specific/desktop_exchange/subwidgets/desktop_trade_history.dart'; import 'package:stackwallet/pages_desktop_specific/desktop_exchange/subwidgets/desktop_trade_history.dart';
import 'package:stackwallet/providers/global/prefs_provider.dart';
import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart';
import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_loading_overlay.dart';
import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart'; import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart'; import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart';
class DesktopExchangeView extends StatefulWidget { class DesktopExchangeView extends ConsumerStatefulWidget {
const DesktopExchangeView({Key? key}) : super(key: key); const DesktopExchangeView({Key? key}) : super(key: key);
static const String routeName = "/desktopExchange"; static const String routeName = "/desktopExchange";
@override @override
State<DesktopExchangeView> createState() => _DesktopExchangeViewState(); ConsumerState<DesktopExchangeView> createState() =>
_DesktopExchangeViewState();
} }
class _DesktopExchangeViewState extends State<DesktopExchangeView> { class _DesktopExchangeViewState extends ConsumerState<DesktopExchangeView> {
bool _initialCachePopulationUnderway = false;
@override
void initState() {
if (!ref.read(prefsChangeNotifierProvider).externalCalls) {
if (ExchangeDataLoadingService.currentCacheVersion <
ExchangeDataLoadingService.cacheVersion) {
_initialCachePopulationUnderway = true;
ExchangeDataLoadingService.instance.onLoadingComplete = () {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
setState(() {
_initialCachePopulationUnderway = false;
});
});
};
}
ExchangeDataLoadingService.instance
.init()
.then((_) => ExchangeDataLoadingService.instance.loadAll());
} else if (ExchangeDataLoadingService.instance.isLoading &&
ExchangeDataLoadingService.currentCacheVersion <
ExchangeDataLoadingService.cacheVersion) {
_initialCachePopulationUnderway = true;
ExchangeDataLoadingService.instance.onLoadingComplete = () {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
setState(() {
_initialCachePopulationUnderway = false;
});
});
};
}
super.initState();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return DesktopScaffold( return ConditionalParent(
appBar: DesktopAppBar( condition: _initialCachePopulationUnderway,
isCompactHeight: true, builder: (child) {
leading: Padding( return Stack(
children: [
child,
Material(
color: Theme.of(context)
.extension<StackColors>()!
.overlay
.withOpacity(0.6),
child: const CustomLoadingOverlay(
message: "Updating exchange data",
subMessage: "This could take a few minutes",
eventBus: null,
),
)
],
);
},
child: DesktopScaffold(
appBar: DesktopAppBar(
isCompactHeight: true,
leading: Padding(
padding: const EdgeInsets.only(
left: 24,
),
child: Text(
"Exchange",
style: STextStyles.desktopH3(context),
),
),
),
body: Padding(
padding: const EdgeInsets.only( padding: const EdgeInsets.only(
left: 24, left: 24,
right: 24,
bottom: 24,
), ),
child: Text( child: Row(
"Exchange", crossAxisAlignment: CrossAxisAlignment.start,
style: STextStyles.desktopH3(context), children: [
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Exchange details",
style: STextStyles.desktopTextExtraExtraSmall(context),
),
const SizedBox(
height: 16,
),
const RoundedWhiteContainer(
padding: EdgeInsets.all(24),
child: ExchangeForm(),
),
],
),
),
const SizedBox(
width: 16,
),
Expanded(
child: Row(
children: const [
Expanded(
child: DesktopTradeHistory(),
),
],
),
),
],
), ),
), ),
), ),
body: Padding(
padding: const EdgeInsets.only(
left: 24,
right: 24,
bottom: 24,
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Exchange details",
style: STextStyles.desktopTextExtraExtraSmall(context),
),
const SizedBox(
height: 16,
),
const RoundedWhiteContainer(
padding: EdgeInsets.all(24),
child: ExchangeForm(),
),
],
),
),
const SizedBox(
width: 16,
),
Expanded(
child: Row(
children: const [
Expanded(
child: DesktopTradeHistory(),
),
],
),
),
],
),
),
); );
} }
} }

View file

@ -1,5 +1,6 @@
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:isar/isar.dart'; import 'package:isar/isar.dart';
import 'package:stackwallet/hive/db.dart';
import 'package:stackwallet/models/isar/exchange_cache/currency.dart'; import 'package:stackwallet/models/isar/exchange_cache/currency.dart';
import 'package:stackwallet/models/isar/exchange_cache/pair.dart'; import 'package:stackwallet/models/isar/exchange_cache/pair.dart';
import 'package:stackwallet/services/exchange/change_now/change_now_exchange.dart'; import 'package:stackwallet/services/exchange/change_now/change_now_exchange.dart';
@ -16,6 +17,25 @@ class ExchangeDataLoadingService {
Isar? _isar; Isar? _isar;
Isar get isar => _isar!; Isar get isar => _isar!;
VoidCallback? onLoadingError;
VoidCallback? onLoadingComplete;
static const int cacheVersion = 1;
static int get currentCacheVersion =>
DB.instance.get<dynamic>(
boxName: DB.boxNameDBInfo,
key: "exchange_data_cache_version") as int? ??
0;
Future<void> _updateCurrentCacheVersion(int version) async {
await DB.instance.put<dynamic>(
boxName: DB.boxNameDBInfo,
key: "exchange_data_cache_version",
value: version,
);
}
Future<void> init() async { Future<void> init() async {
if (_isar != null && isar.isOpen) return; if (_isar != null && isar.isOpen) return;
_isar = await Isar.open( _isar = await Isar.open(
@ -25,18 +45,23 @@ class ExchangeDataLoadingService {
], ],
directory: (await StackFileSystem.applicationIsarDirectory()).path, directory: (await StackFileSystem.applicationIsarDirectory()).path,
inspector: kDebugMode, inspector: kDebugMode,
// inspector: false,
name: "exchange_cache", name: "exchange_cache",
); );
} }
bool get isLoading => _locked;
bool _locked = false; bool _locked = false;
Future<void> loadAll() async { Future<void> loadAll() async {
print("LOADINGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG: LOCKED=$_locked");
if (!_locked) { if (!_locked) {
_locked = true; _locked = true;
print("LOADINGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG"); Logging.instance.log(
final time = DateTime.now(); "ExchangeDataLoadingService.loadAll starting...",
level: LogLevel.Info,
);
final start = DateTime.now();
try { try {
await Future.wait([ await Future.wait([
_loadChangeNowCurrencies(), _loadChangeNowCurrencies(),
@ -46,13 +71,18 @@ class ExchangeDataLoadingService {
// loadSimpleswapFloatingRateCurrencies(ref), // loadSimpleswapFloatingRateCurrencies(ref),
loadMajesticBankCurrencies(), loadMajesticBankCurrencies(),
]); ]);
Logging.instance.log(
print( "ExchangeDataLoadingService.loadAll finished in ${DateTime.now().difference(start).inSeconds} seconds",
"LOADINGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG done in ${DateTime.now().difference(time).inSeconds} seconds"); level: LogLevel.Info,
);
onLoadingComplete?.call();
await _updateCurrentCacheVersion(cacheVersion);
} catch (e, s) { } catch (e, s) {
Logging.instance.log( Logging.instance.log(
"ExchangeDataLoadingService.loadAll failed: $e\n$s", "ExchangeDataLoadingService.loadAll failed after ${DateTime.now().difference(start).inSeconds} seconds: $e\n$s",
level: LogLevel.Error); level: LogLevel.Error,
);
onLoadingError?.call();
} }
_locked = false; _locked = false;
} }
@ -82,7 +112,7 @@ class ExchangeDataLoadingService {
Future<void> _loadChangeNowFixedRatePairs() async { Future<void> _loadChangeNowFixedRatePairs() async {
final exchange = ChangeNowExchange.instance; final exchange = ChangeNowExchange.instance;
final responsePairs = await exchange.getAllPairs(true); final responsePairs = await compute(exchange.getAllPairs, true);
if (responsePairs.value != null) { if (responsePairs.value != null) {
await isar.writeTxn(() async { await isar.writeTxn(() async {
@ -107,7 +137,7 @@ class ExchangeDataLoadingService {
Future<void> _loadChangeNowEstimatedRatePairs() async { Future<void> _loadChangeNowEstimatedRatePairs() async {
final exchange = ChangeNowExchange.instance; final exchange = ChangeNowExchange.instance;
final responsePairs = await exchange.getAllPairs(false); final responsePairs = await compute(exchange.getAllPairs, false);
if (responsePairs.value != null) { if (responsePairs.value != null) {
await isar.writeTxn(() async { await isar.writeTxn(() async {