diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 9ea9b31a..30b19b6d 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -383,7 +383,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = WQ5H736A22; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -518,7 +518,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = WQ5H736A22; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -548,7 +548,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = WQ5H736A22; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( diff --git a/lib/common/consts/settings.dart b/lib/common/consts/settings.dart index 52434fc7..ed9fa29c 100644 --- a/lib/common/consts/settings.dart +++ b/lib/common/consts/settings.dart @@ -148,8 +148,8 @@ const String cross_chain_transfer_address_laminar = '5CLaminarAUSDCrossChainTransferxxxxxxxxxxxxxwisu'; /// app versions -const String app_beta_version = 'v1.0.0-beta.3'; -const int app_beta_version_code = 1003; +const String app_beta_version = 'v1.0.0-beta.4'; +const int app_beta_version_code = 1004; /// js code versions const Map js_code_version_map = { diff --git a/lib/page/governance/govEntry.dart b/lib/page/governance/govEntry.dart index 8c142393..eb74ffa2 100644 --- a/lib/page/governance/govEntry.dart +++ b/lib/page/governance/govEntry.dart @@ -47,7 +47,16 @@ class GovEntry extends StatelessWidget { ? 'polkadot' : 'kusama'; if (store.settings.loading) { - return CupertinoActivityIndicator(); + return Container( + padding: EdgeInsets.only( + top: MediaQuery.of(context).size.width / 2), + child: Column( + children: [ + CupertinoActivityIndicator(), + Text(I18n.of(context).assets['node.connecting']), + ], + ), + ); } return ListView( padding: EdgeInsets.all(16), diff --git a/lib/page/staking/actions/actions.dart b/lib/page/staking/actions/actions.dart index 87607550..a97a4870 100644 --- a/lib/page/staking/actions/actions.dart +++ b/lib/page/staking/actions/actions.dart @@ -79,7 +79,7 @@ class _StakingActions extends State setState(() { _rewardLoading = true; }); - Map res = await webApi.staking.updateStakingRewards(); + await webApi.staking.updateStakingRewards(); if (mounted) { setState(() { _rewardLoading = false; @@ -188,16 +188,23 @@ class _StakingActions extends State if (hasData) { store.account.pubKeyAddressMap[store.settings.endpoint.ss58] .forEach((k, v) { - if (v == store.staking.ownStashInfo.controllerId) { + if (store.staking.ownStashInfo.isOwnStash && + v == store.staking.ownStashInfo.controllerId) { account02PubKey = k; + return; + } + if (store.staking.ownStashInfo.isOwnController && + v == store.staking.ownStashInfo.stashId) { + account02PubKey = k; + return; } }); } AccountData acc02; - int acc02Index = store.account.accountList + int acc02Index = store.account.accountListAll .indexWhere((i) => i.pubKey == account02PubKey); if (acc02Index >= 0) { - acc02 = store.account.accountList[acc02Index]; + acc02 = store.account.accountListAll[acc02Index]; } final symbol = store.settings.networkState.tokenSymbol; @@ -220,7 +227,15 @@ class _StakingActions extends State margin: EdgeInsets.fromLTRB(16, 12, 16, 24), padding: EdgeInsets.all(16), child: !hasData - ? CupertinoActivityIndicator() + ? Container( + padding: EdgeInsets.only(top: 80, bottom: 80), + child: Column( + children: [ + CupertinoActivityIndicator(), + Text(I18n.of(context).assets['node.connecting']), + ], + ), + ) : Column( children: [ Row( @@ -333,9 +348,6 @@ class _StakingActions extends State return Observer( builder: (_) { - if (store.settings.loading) { - return CupertinoActivityIndicator(); - } List list = [ _buildActionCard(), Container( @@ -396,8 +408,8 @@ class RowAccount02 extends StatelessWidget { void _showActions(BuildContext context) { var dic = I18n.of(context).staking; - final isStash = stashInfo.stashId == accountId; - String actionAccountTitle = isStash ? dic['controller'] : dic['stash']; + String actionAccountTitle = + stashInfo.isOwnStash ? dic['controller'] : dic['stash']; String importAccountText = '${dic['action.import']}$actionAccountTitle'; String changeAccountText = dic['action.use'] + actionAccountTitle + dic['action.operate']; @@ -493,16 +505,18 @@ class RowAccount02 extends StatelessWidget { ], ), ), - controllerId == stashId - ? Container() - : GestureDetector( - child: Container( - width: 80, - height: 18, - child: Image.asset('assets/images/staking/set.png'), + Expanded( + child: controllerId == stashId + ? Container() + : GestureDetector( + child: Container( + width: 80, + height: 18, + child: Image.asset('assets/images/staking/set.png'), + ), + onTap: () => _showActions(context), ), - onTap: () => _showActions(context), - ) + ) ], ) : Container(), @@ -674,15 +688,17 @@ class StakingActionsPanel extends StatelessWidget { bool setControllerDisabled = true; Function onSetControllerTap = () => null; if (isStash) { - if (bonded > BigInt.zero) { + if (stashInfo.controllerId != null) { setControllerDisabled = false; onSetControllerTap = () => Navigator.of(context) .pushNamed(SetControllerPage.route, arguments: controller); - if (stashInfo.isOwnStash) { + if (stashInfo.isOwnController) { setPayeeDisabled = false; - onSetPayeeTap = - () => Navigator.of(context).pushNamed(SetPayeePage.route); + onSetPayeeTap = () => Navigator.of(context).pushNamed( + SetPayeePage.route, + arguments: stashInfo.destinationId, + ); } } else { bondButtonString = dic['action.bond']; @@ -690,8 +706,10 @@ class StakingActionsPanel extends StatelessWidget { } else { if (bonded > BigInt.zero) { setPayeeDisabled = false; - onSetPayeeTap = - () => Navigator.of(context).pushNamed(SetPayeePage.route); + onSetPayeeTap = () => Navigator.of(context).pushNamed( + SetPayeePage.route, + arguments: stashInfo.destinationId, + ); } } @@ -718,7 +736,10 @@ class StakingActionsPanel extends StatelessWidget { ], ), onTap: () { - if (isStash && bonded == BigInt.zero) { + /// if not bonded, we can go to bond page. + /// 1. it has no controller + /// 2. it's stash is itself(it's not controller of another acc) + if (stashInfo.controllerId == null && isStash) { Navigator.of(context).pushNamed(BondPage.route); return; } @@ -726,19 +747,40 @@ class StakingActionsPanel extends StatelessWidget { context: context, builder: (BuildContext context) => CupertinoActionSheet( actions: [ + /// disable bondExtra button if account is not stash CupertinoActionSheetAction( - child: Text(dic['action.bondExtra']), - onPressed: () { - Navigator.of(context).pop(); - Navigator.of(context).pushNamed(BondExtraPage.route); - }, + child: Text( + dic['action.bondExtra'], + style: TextStyle( + color: !isStash ? disabledColor : actionButtonColor, + ), + ), + onPressed: !isStash + ? () => {} + : () { + Navigator.of(context).pop(); + Navigator.of(context) + .pushNamed(BondExtraPage.route); + }, ), + + /// disable unbond button if account is not controller CupertinoActionSheetAction( - child: Text(dic['action.unbond']), - onPressed: () { - Navigator.of(context).pop(); - Navigator.of(context).pushNamed(UnBondPage.route); - }, + child: Text( + dic['action.unbond'], + style: TextStyle( + color: isStash && !stashInfo.isOwnController + ? disabledColor + : actionButtonColor, + ), + ), + onPressed: isStash && !stashInfo.isOwnController + ? () => {} + : () { + Navigator.of(context).pop(); + Navigator.of(context) + .pushNamed(UnBondPage.route); + }, ), ], cancelButton: CupertinoActionSheetAction( diff --git a/lib/page/staking/actions/setPayeePage.dart b/lib/page/staking/actions/setPayeePage.dart index 1fdd8206..c539bec6 100644 --- a/lib/page/staking/actions/setPayeePage.dart +++ b/lib/page/staking/actions/setPayeePage.dart @@ -23,7 +23,7 @@ class _SetPayeePageState extends State { final _rewardToOptions = ['Staked', 'Stash', 'Controller']; - int _rewardTo = 0; + int _rewardTo; void _onSubmit() { var dic = I18n.of(context).staking; @@ -73,10 +73,10 @@ class _SetPayeePageState extends State { @override Widget build(BuildContext context) { - var dic = I18n.of(context).staking; - String address = store.account.currentAddress; + final dic = I18n.of(context).staking; + final defaultValue = ModalRoute.of(context).settings.arguments ?? 0; - var rewardToOptions = + final rewardToOptions = _rewardToOptions.map((i) => dic['reward.$i']).toList(); return Scaffold( @@ -100,7 +100,8 @@ class _SetPayeePageState extends State { ), ListTile( title: Text(dic['bond.reward']), - subtitle: Text(rewardToOptions[_rewardTo]), + subtitle: + Text(rewardToOptions[_rewardTo ?? defaultValue]), trailing: Icon(Icons.arrow_forward_ios, size: 18), onTap: () { showCupertinoModalPopup( @@ -113,7 +114,7 @@ class _SetPayeePageState extends State { backgroundColor: Colors.white, itemExtent: 56, scrollController: FixedExtentScrollController( - initialItem: _rewardTo), + initialItem: defaultValue), children: rewardToOptions .map((i) => Padding( padding: EdgeInsets.all(12), diff --git a/lib/page/staking/validators/nominatePage.dart b/lib/page/staking/validators/nominatePage.dart index 58d45c71..ef3a7867 100644 --- a/lib/page/staking/validators/nominatePage.dart +++ b/lib/page/staking/validators/nominatePage.dart @@ -171,25 +171,28 @@ class _NominatePageState extends State { void initState() { super.initState(); - setState(() { - store.staking.validatorsAll.forEach((i) { - _notSelected.add(i); - _selectedMap[i.accountId] = false; - }); - store.staking.nominatingList.forEach((i) { - _selected.add(i); - _notSelected.removeWhere((item) => item.accountId == i.accountId); - _selectedMap[i.accountId] = true; - }); + WidgetsBinding.instance.addPostFrameCallback((_) { + setState(() { + store.staking.validatorsAll.forEach((i) { + _notSelected.add(i); + _selectedMap[i.accountId] = false; + }); + print(store.staking.nominatingList.length); + store.staking.nominatingList.forEach((i) { + _selected.add(i); + _notSelected.removeWhere((item) => item.accountId == i.accountId); + _selectedMap[i.accountId] = true; + }); - // set recommended selected - List recommended = _notSelected.toList(); - recommended.retainWhere((i) => - store.staking.recommendedValidatorList.indexOf(i.accountId) > -1); - recommended.forEach((i) { - _selected.add(i); - _notSelected.removeWhere((item) => item.accountId == i.accountId); - _selectedMap[i.accountId] = true; + // set recommended selected + List recommended = _notSelected.toList(); + recommended.retainWhere((i) => + store.staking.recommendedValidatorList.indexOf(i.accountId) > -1); + recommended.forEach((i) { + _selected.add(i); + _notSelected.removeWhere((item) => item.accountId == i.accountId); + _selectedMap[i.accountId] = true; + }); }); }); } diff --git a/lib/page/staking/validators/overview.dart b/lib/page/staking/validators/overview.dart index 94e7648c..f11d0a4e 100644 --- a/lib/page/staking/validators/overview.dart +++ b/lib/page/staking/validators/overview.dart @@ -2,6 +2,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:polka_wallet/common/components/textTag.dart'; +import 'package:polka_wallet/page/account/txConfirmPage.dart'; import 'package:polka_wallet/page/staking/validators/nominatePage.dart'; import 'package:polka_wallet/page/staking/validators/validatorDetailPage.dart'; import 'package:polka_wallet/service/substrateApi/api.dart'; @@ -61,6 +62,58 @@ class _StakingOverviewPageState extends State } } + void _onSetPayee() { + var dic = I18n.of(context).staking; + showCupertinoModalPopup( + context: context, + builder: (BuildContext context) => CupertinoActionSheet( + actions: [ + CupertinoActionSheetAction( + child: Text( + dic['action.nominee'], + ), + onPressed: () { + Navigator.of(context).popAndPushNamed(NominatePage.route); + }, + ), + CupertinoActionSheetAction( + child: Text( + dic['action.chill'], + ), + onPressed: () { + Navigator.of(context).pop(); + _chill(); + }, + ), + ], + cancelButton: CupertinoActionSheetAction( + child: Text(I18n.of(context).home['cancel']), + onPressed: () { + Navigator.pop(context); + }, + ), + ), + ); + } + + void _chill() { + var dic = I18n.of(context).staking; + var args = { + "title": dic['action.chill'], + "txInfo": { + "module": 'staking', + "call": 'chill', + }, + "detail": 'chill', + "params": [], + 'onFinish': (BuildContext txPageContext, Map res) { + Navigator.popUntil(txPageContext, ModalRoute.withName('/')); + globalNominatingRefreshKey.currentState.show(); + } + }; + Navigator.of(context).pushNamed(TxConfirmPage.route, arguments: args); + } + Widget _buildTopCard(BuildContext context) { var dic = I18n.of(context).staking; bool hashData = store.staking.ownStashInfo != null && @@ -116,35 +169,21 @@ class _StakingOverviewPageState extends State width: 100, child: isController && bonded > 0 ? GestureDetector( - child: nominators.length > 0 - ? Column( - children: [ - OutlinedCircle( - icon: Icons.add, - color: actionButtonColor, - ), - Text( - dic[nominators.length > 0 - ? 'action.nominee' - : 'action.nominate'], - style: TextStyle(color: actionButtonColor), - ) - ], - ) - : Column( - children: [ - OutlinedCircle( - icon: Icons.add, - color: actionButtonColor, - ), - Text( - dic['action.nominate'], - style: TextStyle(color: actionButtonColor), - ) - ], - ), - onTap: () => - Navigator.pushNamed(context, NominatePage.route), + child: Column( + children: [ + OutlinedCircle( + icon: Icons.add, + color: actionButtonColor, + ), + Text( + dic[nominators.length > 0 + ? 'action.nominee' + : 'action.nominate'], + style: TextStyle(color: actionButtonColor), + ) + ], + ), + onTap: _onSetPayee, ) : Column( children: [ @@ -412,7 +451,8 @@ class _StakingOverviewPageState extends State } class _NomineeItem extends StatelessWidget { - _NomineeItem(this.validator, this.active, this.accInfoMap, {this.waiting}); + _NomineeItem(this.validator, this.active, this.accInfoMap, + {this.waiting = false}); final ValidatorData validator; final bool active; diff --git a/lib/service/substrateApi/apiStaking.dart b/lib/service/substrateApi/apiStaking.dart index b9fd6ac8..60d9d2e4 100644 --- a/lib/service/substrateApi/apiStaking.dart +++ b/lib/service/substrateApi/apiStaking.dart @@ -84,9 +84,11 @@ class ApiStaking { } Future updateStakingRewards() async { - Map res = await apiRoot.subScanApi.fetchRewardTxsAsync( + final address = + store.staking.ownStashInfo?.stashId ?? store.account.currentAddress; + final res = await apiRoot.subScanApi.fetchRewardTxsAsync( page: 0, - sender: store.account.currentAddress, + sender: address, network: store.settings.networkName.toLowerCase(), ); diff --git a/lib/store/staking/staking.dart b/lib/store/staking/staking.dart index 52661fb9..a98345e7 100644 --- a/lib/store/staking/staking.dart +++ b/lib/store/staking/staking.dart @@ -108,12 +108,13 @@ abstract class _StakingStore with Store { @computed List get nominatingList { - List nominators = ledger['nominators']; - if (nominators == null) { + if (ownStashInfo == null || + ownStashInfo.nominating == null || + ownStashInfo.nominating.length == 0) { return []; } - return List.of( - validatorsInfo.where((i) => nominators.indexOf(i.accountId) >= 0)); + return List.of(validatorsInfo + .where((i) => ownStashInfo.nominating.indexOf(i.accountId) >= 0)); } @computed diff --git a/lib/utils/i18n/staking.dart b/lib/utils/i18n/staking.dart index 03c5799e..011b103d 100644 --- a/lib/utils/i18n/staking.dart +++ b/lib/utils/i18n/staking.dart @@ -17,7 +17,7 @@ const Map enStaking = { 'commission': 'Commission', 'points': 'Points', 'judgements': 'Judgements', - 'txs': 'Staking Records', + 'txs': 'Tx history', 'txs.reward': 'Reward/Slash', 'txs.reward.reward': 'Reward', 'txs.reward.slash': 'Slash', @@ -87,7 +87,7 @@ const Map zhStaking = { 'commission': '佣金', 'points': '得分', 'judgements': '评价', - 'txs': '质押记录', + 'txs': '操作记录', 'txs.reward': '收益/罚金', 'txs.reward.reward': '收益', 'txs.reward.slash': '罚金', diff --git a/pubspec.yaml b/pubspec.yaml index 98f12e8a..3e9c2f60 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -11,7 +11,7 @@ description: PolkaWallet made with Flutter. # 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.0.0+1003 +version: 1.0.0+1004 environment: sdk: ">=2.1.0 <3.0.0"