Encrypted peer-to-peer IM for data security. Own data, own privacy. (Rust+Flutter)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

364 lines
12 KiB

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:esse/utils/adaptive.dart';
import 'package:esse/utils/better_print.dart';
import 'package:esse/l10n/localizations.dart';
import 'package:esse/widgets/button_text.dart';
import 'package:esse/widgets/input_text.dart';
import 'package:esse/widgets/default_core_show.dart';
import 'package:esse/global.dart';
import 'package:esse/options.dart';
import 'package:esse/rpc.dart';
import 'package:esse/apps/wallet/models.dart';
class WalletDetail extends StatefulWidget {
const WalletDetail({Key? key}) : super(key: key);
@override
_WalletDetailState createState() => _WalletDetailState();
}
class _WalletDetailState extends State<WalletDetail> with SingleTickerProviderStateMixin {
TabController? _tabController;
bool _needGenerate = false;
List<Address> _addresses = [];
Address? _selectedAddress;
List<Network> _networks = [];
Network? _selectedNetwork;
Token _mainToken = Token();
List<Token> _tokens = [];
List tokens = [
['USDT', '2000', '2000', 'assets/logo/logo_tether.png'],
['XXX', '100', '1000', 'assets/logo/logo_eth.png'],
['FFF', '100', '1000', 'assets/logo/logo_eth.png'],
];
@override
void initState() {
_tabController = new TabController(length: 2, vsync: this);
rpc.addListener('wallet-generate', _walletGenerate, false);
rpc.addListener('wallet-balance', _walletBalance, false);
super.initState();
Future.delayed(Duration.zero, _load);
}
_walletGenerate(List params) {
final address = Address.fromList(params);
bool isNew = true;
this._addresses.forEach((addr) {
if (addr.address == address.address) {
isNew = false;
}
});
if (isNew) {
this._addresses.add(address);
setState(() {});
}
}
_walletBalance(List params) {
print(params);
final address = params[0];
final network = NetworkExtension.fromInt(params[1]);
final contract = params[2];
final balance = params[3];
// TODO check token.
this._mainToken = Token.eth(network);
this._mainToken.balance(balance);
setState(() {});
}
_load() async {
final res = await httpPost(Global.httpRpc, 'wallet-list', []);
if (res.isOk) {
this._addresses.clear();
res.params.forEach((param) {
this._addresses.add(Address.fromList(param));
});
if (this._addresses.length == 0) {
this._needGenerate = true;
}
setState(() {});
} else {
// TODO tostor error
print(res.error);
}
}
_changeAddress(Address address) {
this._selectedAddress = address;
this._networks = address.networks();
if (!this._networks.contains(this._selectedNetwork)) {
_changeNetwork(this._networks[0]);
}
}
_changeNetwork(Network network) {
this._selectedNetwork = network;
rpc.send('wallet-balance', [
this._selectedNetwork!.toInt(), this._selectedAddress!.address
]);
print('sended balances');
}
@override
Widget build(BuildContext context) {
final color = Theme.of(context).colorScheme;
final lang = AppLocalizations.of(context);
if (this._addresses.length == 0 && !this._needGenerate) {
return Scaffold(
appBar: AppBar(title: Text(lang.loadMore)),
body: const DefaultCoreShow(),
);
}
if (this._addresses.length == 0 && this._needGenerate) {
return Scaffold(
appBar: AppBar(title: Text(lang.wallet)),
body: DefaultCoreShow(
child: ElevatedButton(
style: ElevatedButton.styleFrom(onPrimary: color.surface),
onPressed: () {
rpc.send('wallet-generate', [ChainToken.ETH.toInt(), ""]);
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 16.0),
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.lock),
const SizedBox(width: 8.0),
const Text('生成以太坊地址'),
]
)
)
))
);
}
if (this._selectedAddress == null) {
_changeAddress(this._addresses[0]);
}
return Scaffold(
appBar: AppBar(
title: DropdownButton<Network>(
icon: Container(),
underline: Container(),
value: this._selectedNetwork,
onChanged: (Network? value) {
if (value != null) {
setState(() {
_changeNetwork(value);
});
}
},
items: this._networks.map((Network network) {
final params = network.params();
return DropdownMenuItem<Network>(
value: network,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 6.0),
decoration: BoxDecoration(
border: Border.all(width: 1.0, color: params[1]),
borderRadius: BorderRadius.circular(25.0)
),
child: Row(
children: <Widget>[
Icon(Icons.public, color: params[1], size: 18.0),
const SizedBox(width: 10),
Text(params[0], style: TextStyle(color: params[1], fontSize: 14.0)),
],
)),
);
}).toList(),
),
actions: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: DropdownButton<Address>(
icon: Container(),
underline: Container(),
value: this._selectedAddress,
onChanged: (Address? value) {
if (value != null) {
setState(() {
_changeAddress(value);
});
}
},
items: this._addresses.map((Address addr) {
return DropdownMenuItem<Address>(
value: addr,
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 10.0),
width: 40.0,
height: 40.0,
decoration: BoxDecoration(
color: color.surface,
borderRadius: BorderRadius.circular(25.0)
),
child: Center(child: Text(addr.icon()))
),
);
}).toList(),
),
)
]
),
body: Container(
alignment: Alignment.topCenter,
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: Column(
children:[
InkWell(
onTap: () {
Clipboard.setData(ClipboardData(text: this._selectedAddress!.address));
},
child: Container(
padding: const EdgeInsets.symmetric(vertical: 10.0),
alignment: Alignment.center,
decoration: new BoxDecoration(
border: new Border(bottom:
const BorderSide(width: 1.0, color: Color(0xA0ADB0BB)))),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(this._selectedAddress!.name, style: TextStyle(fontSize: 18.0)),
const SizedBox(height: 4.0),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(this._selectedAddress!.short(),
style: TextStyle(color: Color(0xFFADB0BB))),
const SizedBox(width: 8.0),
Icon(Icons.copy, size: 16.0, color: color.primary),
]
)
]
),
),
),
Container(
padding: const EdgeInsets.symmetric(vertical: 20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 36.0,
height: 36.0,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(this._mainToken.logo),
fit: BoxFit.cover,
),
),
),
Container(
height: 60.0,
alignment: Alignment.center,
child: Text(
"${this._mainToken.amount} ${this._mainToken.name}",
style: TextStyle(fontSize: 24.0, fontWeight: FontWeight.bold)),
),
Text('\$1000', style: TextStyle(color: Color(0xFFADB0BB))),
const SizedBox(height: 8.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
TextButton(
onPressed: () {
setState(() {});
},
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
decoration: BoxDecoration(
color: Color(0xFF6174FF),
borderRadius: BorderRadius.circular(25.0)
),
child: Center(child: Text('Send', style: TextStyle(color: Colors.white)))
)
),
TextButton(
onPressed: () {
setState(() {});
},
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
decoration: BoxDecoration(
color: Color(0xFF6174FF),
borderRadius: BorderRadius.circular(25.0)
),
child: Center(child: Text('Receive', style: TextStyle(color: Colors.white)))
)
),
]
),
]
)
),
TabBar(
unselectedLabelColor: color.onSurface,
labelColor: Color(0xFF6174FF),
tabs: [
Tab(text: 'Assets'),
Tab(text: 'Activity'),
],
controller: _tabController!,
indicatorSize: TabBarIndicatorSize.tab,
),
Expanded(
child: TabBarView(
children: [
ListView.separated(
separatorBuilder: (BuildContext context, int index) => const Divider(),
itemCount: tokens.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: Container(
width: 36.0,
height: 36.0,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(tokens[index][3]),
fit: BoxFit.cover,
),
),
),
title: Text(tokens[index][1] + ' ' + tokens[index][0]),
subtitle: Text('\$' + tokens[index][2]),
trailing: IconButton(icon: Icon(Icons.arrow_forward_ios),
onPressed: () {}),
);
}
),
ListView.separated(
separatorBuilder: (BuildContext context, int index) => const Divider(),
itemCount: 10,
itemBuilder: (BuildContext context, int index) {
return Container(
child: Text('TODO ${index}'),
);
}
),
],
controller: _tabController!,
),
),
]
)
),
);
}
}