mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-20 06:08:34 +02:00
feat: initial hive -> SQLite (#2502)
* feat: initial hive -> SQLite Includes migration script and initial work done to remove dependency on hive generators. Also contains some refactoring to make sync code async. Features new dev screen that lists all SQLite tables Aspects that need testing: - backups (from this version, and from previous versions as well) - wallet loading / wallet list - almost everything else - renaming - deletion - sorting in wallet list - wallet groups - wallet seed/keys - wallet switching - wallet creation / restore - all methods - wallet address page - hardware wallet connection (and prompts from mall screens) - contacts - advanced settings in wallet creation - derivation paths - some minor wownero fixes - base, hardware wallets * fix: build errors * fix: Bad state: No element in backup restore * address comments from review * fix: HardwareWalletType
This commit is contained in:
@@ -17,6 +17,7 @@ import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:flutter_slidable/flutter_slidable.dart';
|
||||
|
||||
class ContactListPage extends BasePage {
|
||||
@@ -150,7 +151,9 @@ class _ContactPageBodyState extends State<ContactPageBody> with SingleTickerProv
|
||||
child: TabBarView(
|
||||
controller: _tabController,
|
||||
children: [
|
||||
_buildWalletContacts(context),
|
||||
Observer(
|
||||
builder: (final BuildContext context) => _buildWalletContacts(context),
|
||||
),
|
||||
ContactListBody(
|
||||
contactListViewModel: widget.contactListViewModel,
|
||||
tabController: _tabController,
|
||||
|
||||
@@ -351,7 +351,7 @@ class _WalletNameFormState extends State<WalletNameForm> {
|
||||
_formProcessing = false;
|
||||
return;
|
||||
}
|
||||
if (_walletNewVM.nameExists(_walletNewVM.name)) {
|
||||
if (await _walletNewVM.nameExists(_walletNewVM.name)) {
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (_) {
|
||||
|
||||
@@ -258,7 +258,7 @@ class WalletRestorePage extends BasePage {
|
||||
return;
|
||||
}
|
||||
|
||||
if (walletRestoreViewModel.nameExists(name)) {
|
||||
if (await walletRestoreViewModel.nameExists(name)) {
|
||||
showNameExistsAlert(formContext!);
|
||||
_formProcessing = false;
|
||||
return;
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:cake_wallet/entities/priority_for_wallet_type.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/screens/dev/moneroc_cache_debug.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/setting_priority_picker_cell.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart';
|
||||
@@ -11,6 +12,7 @@ import 'package:cake_wallet/utils/feature_flag.dart';
|
||||
import 'package:cake_wallet/view_model/settings/other_settings_view_model.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:cw_core/db/sqlite.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
|
||||
@@ -144,6 +146,16 @@ class OtherSettingsPage extends BasePage {
|
||||
handler: (BuildContext context) =>
|
||||
Navigator.of(context).pushNamed(Routes.devExchangeProviderLogs),
|
||||
),
|
||||
if (FeatureFlag.hasDevOptions)
|
||||
SettingsCellWithArrow(
|
||||
title: '[dev] browse sqlite db',
|
||||
handler: (BuildContext context) async {
|
||||
final data = await dumpDb();
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(builder: (context) => JsonExplorerPage(data: data, title: 'sqlite db')),
|
||||
);
|
||||
}
|
||||
),
|
||||
Spacer(),
|
||||
SettingsVersionCell(
|
||||
title: S.of(context).version(_otherSettingsViewModel.currentVersion),
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:another_flushbar/flushbar.dart';
|
||||
import 'package:cake_wallet/core/wallet_name_validator.dart';
|
||||
import 'package:cake_wallet/entities/wallet_edit_page_arguments.dart';
|
||||
@@ -10,6 +12,7 @@ import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cake_wallet/utils/show_bar.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_list/wallet_edit_view_model.dart';
|
||||
import 'package:cw_core/utils/print_verbose.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
@@ -86,7 +89,7 @@ class WalletEditPage extends BasePage {
|
||||
onPressed: () async {
|
||||
if (_formKey.currentState?.validate() ?? false) {
|
||||
if (!pageArguments.isWalletGroup &&
|
||||
pageArguments.walletNewVM!
|
||||
await pageArguments.walletNewVM!
|
||||
.nameExists(walletEditViewModel.newName)) {
|
||||
showPopUp<void>(
|
||||
context: context,
|
||||
@@ -217,9 +220,12 @@ class WalletEditPage extends BasePage {
|
||||
}
|
||||
|
||||
Future<void> hideProgressText() async {
|
||||
await Future.delayed(Duration(milliseconds: 50), () {
|
||||
_progressBar?.dismiss();
|
||||
_progressBar = null;
|
||||
});
|
||||
try {
|
||||
await Future.delayed(Duration(milliseconds: 250));
|
||||
await _progressBar?.dismiss();
|
||||
} catch (e) {
|
||||
printV(e);
|
||||
}
|
||||
_progressBar = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:another_flushbar/flushbar.dart';
|
||||
import 'package:cake_wallet/core/auth_service.dart';
|
||||
import 'package:cake_wallet/core/new_wallet_arguments.dart';
|
||||
@@ -27,6 +29,7 @@ import 'package:cake_wallet/view_model/wallet_list/wallet_list_view_model.dart';
|
||||
import 'package:cake_wallet/wallet_type_utils.dart';
|
||||
import 'package:cw_core/currency_for_wallet_type.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/utils/print_verbose.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
@@ -40,17 +43,26 @@ class WalletListPage extends BasePage {
|
||||
|
||||
final WalletListViewModel walletListViewModel;
|
||||
final AuthService authService;
|
||||
final Function(BuildContext)? onWalletLoaded;
|
||||
final Future<void> Function(BuildContext)? onWalletLoaded;
|
||||
|
||||
@override
|
||||
String get title => S.current.wallets;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) => WalletListBody(
|
||||
Widget body(BuildContext context) => Observer(
|
||||
builder: (_) {
|
||||
if (walletListViewModel.singleWalletsList.isEmpty && walletListViewModel.multiWalletGroups.isEmpty) {
|
||||
return Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
}
|
||||
return WalletListBody(
|
||||
walletListViewModel: walletListViewModel,
|
||||
authService: authService,
|
||||
onWalletLoaded: onWalletLoaded ?? (context) => Navigator.of(context).pop(),
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
@override
|
||||
Widget trailing(BuildContext context) {
|
||||
@@ -459,7 +471,7 @@ class WalletListBodyState extends State<WalletListBody> {
|
||||
|
||||
try {
|
||||
final requireHardwareWalletConnection =
|
||||
widget.walletListViewModel.requireHardwareWalletConnection(wallet);
|
||||
await widget.walletListViewModel.requireHardwareWalletConnection(wallet);
|
||||
if (requireHardwareWalletConnection) {
|
||||
bool didConnect = false;
|
||||
await Navigator.of(context).pushNamed(
|
||||
@@ -489,22 +501,20 @@ class WalletListBodyState extends State<WalletListBody> {
|
||||
buttonAction: () => Navigator.of(context).pop()),
|
||||
);
|
||||
}
|
||||
|
||||
changeProcessText(S.of(context).wallet_list_loading_wallet(wallet.name));
|
||||
await widget.walletListViewModel.loadWallet(wallet);
|
||||
await hideProgressText();
|
||||
// only pop the wallets route in mobile as it will go back to dashboard page
|
||||
// in desktop platforms the navigation tree is different
|
||||
if (responsiveLayoutUtil.shouldRenderMobileUI) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (this.mounted) {
|
||||
if (requireHardwareWalletConnection) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
widget.onWalletLoaded.call(context);
|
||||
}
|
||||
});
|
||||
// await Future.delayed(Duration(seconds: 1));
|
||||
// if (!this.mounted) return;
|
||||
if (!context.mounted) return;
|
||||
if (requireHardwareWalletConnection) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
await widget.onWalletLoaded.call(context);
|
||||
}
|
||||
unawaited(hideProgressText());
|
||||
} catch (e) {
|
||||
await ExceptionHandler.resetLastPopupDate();
|
||||
final err = e.toString();
|
||||
|
||||
@@ -52,76 +52,79 @@ class _WalletSwitcherContent extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Observer(
|
||||
builder: (_) {
|
||||
final wallets = viewModel.getWallets(filterWalletType);
|
||||
|
||||
if (viewModel.isProcessing) {
|
||||
return Container(
|
||||
height: 200,
|
||||
child: Center(
|
||||
child: CircularProgressIndicator(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return Container(
|
||||
height: 400,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: StandardList(
|
||||
itemCount: wallets.length,
|
||||
itemBuilder: (context, index) {
|
||||
final wallet = wallets[index];
|
||||
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
viewModel.selectWallet(wallet);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
child: Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
height: 60,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
Image.asset(
|
||||
walletTypeToCryptoCurrency(wallet.type).iconPath!,
|
||||
width: 32,
|
||||
height: 32,
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Text(
|
||||
wallet.name,
|
||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
letterSpacing: 0.0,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
return FutureBuilder(
|
||||
future: viewModel.getWallets(filterWalletType),
|
||||
builder: (context, snapshot) => Observer(
|
||||
builder: (_) {
|
||||
final List<WalletInfo> wallets = (snapshot.data ?? []);
|
||||
|
||||
if (viewModel.isProcessing) {
|
||||
return Container(
|
||||
height: 200,
|
||||
child: Center(
|
||||
child: CircularProgressIndicator(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return Container(
|
||||
height: 400,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: StandardList(
|
||||
itemCount: wallets.length,
|
||||
itemBuilder: (context, index) {
|
||||
final wallet = wallets[index];
|
||||
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
viewModel.selectWallet(wallet);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
child: Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
height: 60,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
Image.asset(
|
||||
walletTypeToCryptoCurrency(wallet.type).iconPath!,
|
||||
width: 32,
|
||||
height: 32,
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Text(
|
||||
wallet.name,
|
||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
letterSpacing: 0.0,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user