active account stored in db

Fix Home page shortcuts
This commit is contained in:
Hanh 2023-01-04 18:40:36 +08:00
parent 6b7045934a
commit 130e0b9642
12 changed files with 164 additions and 126 deletions

View File

@ -1,5 +1,4 @@
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:flutter_svg/svg.dart';
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:warp_api/warp_api.dart';
@ -60,7 +59,7 @@ class AccountManagerState extends State<AccountManagerPage> {
itemCount: _accounts.list.length,
itemBuilder: (BuildContext context, int index) {
final a = _accounts.list[index];
final weight = settings.coins[a.coin].active == a.id ? FontWeight.bold : FontWeight.normal;
final weight = a.active ? FontWeight.bold : FontWeight.normal;
final zbal = a.balance / ZECUNIT;
final tbal = a.tbalance / ZECUNIT;
final balance = zbal + tbal;
@ -165,7 +164,6 @@ class AccountManagerState extends State<AccountManagerPage> {
_selectAccount(Account account) async {
active.setActiveAccount(account.coin, account.id);
active.refreshAccount();
if (syncStatus.accountRestored) {
syncStatus.setAccountRestored(false);
final height = await rescanDialog(context);

View File

@ -6,9 +6,7 @@ import 'package:mobx/mobx.dart';
import 'db.dart';
import 'package:warp_api/warp_api.dart';
import 'backup.dart';
import 'coin/coin.dart';
import 'coin/zcash.dart';
import 'main.dart';
import 'store.dart';
@ -19,6 +17,7 @@ class Account {
final int id;
final String name;
final int balance;
bool active = false;
int tbalance = 0;
Account(this.coin, this.id, this.name, this.balance, this.tbalance);
@ -40,9 +39,14 @@ class AccountList {
void refresh() {
List<Account> _list = [];
for (var coin in coins) {
_list.addAll(WarpApi.getAccountList(coin.coin).map((a) => Account(
coin.coin, a.id, a.name!, a.balance, 0)
));
var accounts = WarpApi.getAccountList(coin.coin).map((a) => Account(
coin.coin, a.id, a.name!, a.balance, 0)
).toList();
final id = WarpApi.getActiveAccountId(coin.coin);
if (id != 0) {
accounts.firstWhere((a) => a.id == id).active = true;
}
_list.addAll(accounts);
}
list = _list;
}
@ -66,15 +70,6 @@ class AccountList {
refresh();
}
void saveActive(int coin, int id) {
settings.coins[coin].active = id;
Future.microtask(() async {
final prefs = await SharedPreferences.getInstance();
final def = settings.coins[coin].def;
prefs.setInt("${def.ticker}.active", id);
});
}
Account get(int coin, int id) => list.firstWhere((e) => e.coin == coin && e.id == id, orElse: () => emptyAccount);
}
@ -139,17 +134,16 @@ abstract class _ActiveAccount with Store {
}
else if (aid != active.toId()) {
setActiveAccount(aid.coin, aid.id);
refreshAccount();
}
}
AccountId? getAvailableId(AccountId aid) {
final nid = getAvailableIdForCoin(aid.coin, aid.id);
final nid = getActiveAccountId(aid.coin);
if (nid.id != 0) return nid;
for (var coin_data in settings.coins) {
// look for an account in any other coin
if (coin_data.coin != coin) {
final nid = getAvailableIdForCoin(coin_data.coin, coin_data.active);
final nid = getActiveAccountId(coin_data.coin);
if (nid.id != 0)
return nid;
}
@ -158,30 +152,27 @@ abstract class _ActiveAccount with Store {
return null;
}
// check that the account still exists
// if not, pick any account
// if there are none, return 0
AccountId getAvailableIdForCoin(int coin, int id) {
final newId = WarpApi.getAvailableAccountId(coin, id);
return AccountId(coin, newId);
AccountId getActiveAccountId(int coin) {
final id = WarpApi.getActiveAccountId(coin);
return AccountId(coin, id);
}
@action
void setActiveAccount(int _coin, int _id) {
coin = _coin;
id = _id;
void setActiveAccount(int coin, int id) {
WarpApi.setActiveAccount(coin, id);
Future.microtask(() async {
final prefs = await SharedPreferences.getInstance();
prefs.setInt('coin', coin);
prefs.setInt('account', id);
});
WarpApi.setActiveAccount(coin, id);
if (coin != this.coin || id != this.id) {
this.coin = coin;
this.id = id;
_refreshAccount();
}
}
@action
void refreshAccount() {
final dbr = DbReader(coin, id);
void _refreshAccount() {
coinDef = settings.coins[coin].def;
final accounts = AccountList();
@ -221,7 +212,6 @@ abstract class _ActiveAccount with Store {
@action
void updateBalances() {
final dbr = DbReader(coin, id);
final initialized = balances.initialized;
final prevBalance = balances.balance;
final b = WarpApi.getBalance(coin, id, syncStatus.confirmHeight);

View File

@ -85,12 +85,11 @@ StreamSubscription? subUniLinks;
void handleUri(BuildContext context, Uri uri) {
final scheme = uri.scheme;
final coinDef = settings.coins.firstWhere((c) => c.def.currency == scheme);
final id = settings.coins[coinDef.coin].active;
if (id != 0) {
active.setActiveAccount(coinDef.coin, id);
Navigator.of(context).pushNamed(
'/send', arguments: SendPageArgs(uri: uri.toString()));
}
final coin = coinDef.coin;
final id = WarpApi.getActiveAccountId(coin);
active.setActiveAccount(coin, id);
Navigator.of(context).pushNamed(
'/send', arguments: SendPageArgs(uri: uri.toString()));
}
Future<void> initUniLinks(BuildContext context) async {
@ -112,18 +111,15 @@ void handleQuickAction(BuildContext context, String type) {
final t = type.split(".");
final coin = int.parse(t[0]);
final shortcut = t[1];
final a = settings.coins[coin].active;
if (a != 0) {
active.setActiveAccount(coin, a);
switch (shortcut) {
case 'receive':
Navigator.of(context).pushNamed('/receive');
break;
case 'send':
Navigator.of(context).pushNamed('/send');
break;
}
final id = WarpApi.getActiveAccountId(coin);
active.setActiveAccount(coin, id);
switch (shortcut) {
case 'receive':
Navigator.of(context).pushNamed('/receive');
break;
case 'send':
Navigator.of(context).pushNamed('/send');
break;
}
}

View File

@ -188,7 +188,6 @@ class _AddAccountPageState extends State<AddAccountPage> {
]));
} else {
active.setActiveAccount(_coin, account);
active.refreshAccount();
final nav = Navigator.of(context);
if (_keyController.text != "") {
syncStatus.setAccountRestored(true);

View File

@ -89,25 +89,18 @@ class SendState extends State<SendPage> {
final recipients = widget.args?.recipients ?? [];
_usedBalance = recipients.fold(0, (acc, r) => acc + r.amount);
_newBlockAutorunDispose = autorun((_) {
syncStatus.latestHeight;
setState(() {});
});
Future.microtask(syncStatus.update);
final uri = widget.args?.uri;
if (uri != null)
Future.microtask(() {
_setPaymentURI(uri);
});
active.updateBalances();
final balances = active.balances;
final sBalance = balances.shieldedBalance;
final tBalance = active.tbalance;
final excludedBalance = balances.excludedBalance;
final underConfirmedBalance = balances.underConfirmedBalance;
int? unconfirmedBalance = unconfirmedBalanceStream.value;
_sBalance = sBalance;
_tBalance = tBalance;
_excludedBalance = excludedBalance;
_underConfirmedBalance = underConfirmedBalance;
_unconfirmedBalance = unconfirmedBalance ?? 0;
final templateIds = active.dbReader.loadTemplates();
_templates = templateIds;
}
@ -139,8 +132,20 @@ class SendState extends State<SendPage> {
_memoInitialized = true;
}
var templates = _templates.map((t) => DropdownMenuItem(child: Text(t.title!), value: t)).toList();
active.updateBalances();
final balances = active.balances;
final sBalance = balances.shieldedBalance;
final tBalance = active.tbalance;
final excludedBalance = balances.excludedBalance;
final underConfirmedBalance = balances.underConfirmedBalance;
int? unconfirmedBalance = unconfirmedBalanceStream.value;
_sBalance = sBalance;
_tBalance = tBalance;
_excludedBalance = excludedBalance;
_underConfirmedBalance = underConfirmedBalance;
_unconfirmedBalance = unconfirmedBalance ?? 0;
var templates = _templates.map((t) => DropdownMenuItem(child: Text(t.title!), value: t)).toList();
final addReset = _template != null ? IconButton(onPressed: _resetTemplate, icon: Icon(Icons.close)) : IconButton(onPressed: _addTemplate, icon: Icon(Icons.add));
return Scaffold(

View File

@ -97,7 +97,6 @@ class CoinData = _CoinData with _$CoinData;
abstract class _CoinData with Store {
final int coin;
int active = 0;
int syncedHeight = 0;
final CoinBase def;
@observable bool contactsSaved = true;
@ -269,7 +268,6 @@ abstract class _Settings with Store {
for (var c in coins) {
final ticker = c.def.ticker;
c.active = prefs.getInt("$ticker.active") ?? 0;
c.contactsSaved = prefs.getBool("$ticker.contacts_saved") ?? true;
}
@ -1119,12 +1117,15 @@ class DecodedPaymentURI {
}
class SendPageArgs {
final bool isMulti;
final ContactT? contact;
final String? address;
final String? subject;
final String? uri;
final List<Recipient> recipients;
final bool isMulti; // use multi ...
final List<Recipient> recipients; // recipients
final ContactT? contact; // send to contact
final String? address; // reply to ...
final String? subject; // message
final String? uri; // send to payment URI
SendPageArgs({this.isMulti = false, this.contact, this.address, this.subject, this.uri, this.recipients = const[]});
}

@ -1 +1 @@
Subproject commit 43c348408b3f673be66863f92e61597e552cd8ce
Subproject commit b9726bf29323140f07732ea664fdc1f3447048d7

View File

@ -426,8 +426,12 @@ class WarpApi {
return AccountVec(r).accounts!;
}
static int getAvailableAccountId(int coin, int id) {
return unwrapResultU32(warp_api_lib.get_available_account_id(coin, id));
static int getActiveAccountId(int coin) {
return unwrapResultU32(warp_api_lib.get_active_account(coin));
}
static void setActiveAccountId(int coin, int id) {
unwrapResultU8(warp_api_lib.set_active_account(coin, id));
}
static String getTAddr(int coin, int id) {

View File

@ -124,21 +124,6 @@ class NativeLibrary {
late final _dart_set_active _set_active =
_set_active_ptr.asFunction<_dart_set_active>();
void set_active_account(
int coin,
int id,
) {
return _set_active_account(
coin,
id,
);
}
late final _set_active_account_ptr =
_lookup<ffi.NativeFunction<_c_set_active_account>>('set_active_account');
late final _dart_set_active_account _set_active_account =
_set_active_account_ptr.asFunction<_dart_set_active_account>();
void set_coin_lwd_url(
int coin,
ffi.Pointer<ffi.Int8> lwd_url,
@ -920,22 +905,33 @@ class NativeLibrary {
late final _dart_get_account_list _get_account_list =
_get_account_list_ptr.asFunction<_dart_get_account_list>();
CResult_u32 get_available_account_id(
CResult_u32 get_active_account(
int coin,
) {
return _get_active_account(
coin,
);
}
late final _get_active_account_ptr =
_lookup<ffi.NativeFunction<_c_get_active_account>>('get_active_account');
late final _dart_get_active_account _get_active_account =
_get_active_account_ptr.asFunction<_dart_get_active_account>();
CResult_u8 set_active_account(
int coin,
int id,
) {
return _get_available_account_id(
return _set_active_account(
coin,
id,
);
}
late final _get_available_account_id_ptr =
_lookup<ffi.NativeFunction<_c_get_available_account_id>>(
'get_available_account_id');
late final _dart_get_available_account_id _get_available_account_id =
_get_available_account_id_ptr
.asFunction<_dart_get_available_account_id>();
late final _set_active_account_ptr =
_lookup<ffi.NativeFunction<_c_set_active_account>>('set_active_account');
late final _dart_set_active_account _set_active_account =
_set_active_account_ptr.asFunction<_dart_set_active_account>();
CResult_____c_char get_t_addr(
int coin,
@ -1462,16 +1458,6 @@ typedef _dart_set_active = void Function(
int active,
);
typedef _c_set_active_account = ffi.Void Function(
ffi.Uint8 coin,
ffi.Uint32 id,
);
typedef _dart_set_active_account = void Function(
int coin,
int id,
);
typedef _c_set_coin_lwd_url = ffi.Void Function(
ffi.Uint8 coin,
ffi.Pointer<ffi.Int8> lwd_url,
@ -1984,12 +1970,20 @@ typedef _dart_get_account_list = CResult______u8 Function(
int coin,
);
typedef _c_get_available_account_id = CResult_u32 Function(
typedef _c_get_active_account = CResult_u32 Function(
ffi.Uint8 coin,
);
typedef _dart_get_active_account = CResult_u32 Function(
int coin,
);
typedef _c_set_active_account = CResult_u8 Function(
ffi.Uint8 coin,
ffi.Uint32 id,
);
typedef _dart_get_available_account_id = CResult_u32 Function(
typedef _dart_set_active_account = CResult_u8 Function(
int coin,
int id,
);

View File

@ -1085,21 +1085,14 @@ packages:
name: sensors_plus
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.1"
version: "2.0.1"
sensors_plus_platform_interface:
dependency: transitive
description:
name: sensors_plus_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
sensors_plus_web:
dependency: transitive
description:
name: sensors_plus_web
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.1.3"
share_plus:
dependency: "direct main"
description:
@ -1464,4 +1457,4 @@ packages:
version: "3.1.1"
sdks:
dart: ">=2.18.0 <3.0.0"
flutter: ">=2.10.0"
flutter: ">=2.11.0"

View File

@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.2.17+344
version: 1.2.17+345
environment:
sdk: ">=2.12.0 <3.0.0"
@ -64,7 +64,7 @@ dependencies:
ref: c2c79def4f7fa8c17e9432ca43d307ba0b4a75a3
flutter_speed_dial: ^5.0.0
currency_text_input_formatter: ^2.1.2
sensors_plus: ^1.1.0
sensors_plus: ^2.0.0
connectivity_plus: ^2.2.1
uni_links: ^0.5.1
quick_actions: ^0.6.0

58
smoke-test.md Normal file
View File

@ -0,0 +1,58 @@
# Send YEC & ZEC
- Address: Contact, account, address or QR code
- Amount in coin & fiat
- Max button
- Slider
- Checkbox "include fee"
- Memo
- Subject
- Body
- Reply-To
- Send Templates
# Execution Plan
- t2t, t2z, z2t, z2z
# Receive
- Payment URI
- T, Z, O address types
- Amount & Memo
- Diversified Address
- Copy address to clipboard
# Transparent Account
- Override derivation path
- Shield
# Synchronization
- Recan by date & height
# Accounts
- New, Edit, Delete
- Select default
- Import seed phrase, sk, vk
# Backup
- Backup data
- Save/Load full backup
- Convert to Watchonly
# Contacts
- New, Edit, Delete
- Save to Blockchain
# Settings
- Fiat currency
- number of confirmations
# Desktop integrations
- Send/Receive
- QR code reader
# Cold Wallet
- by QR
- by File
- Broadcast
# Derivation Tool