Browse Source

Domain: add search function

pull/18/head
Sun 4 years ago
parent
commit
5115c468e5
  1. 57
      lib/apps/chat/add.dart
  2. 9
      lib/apps/domain/models.dart
  3. 88
      lib/apps/domain/page.dart
  4. 1
      lib/l10n/localizations.dart
  5. 2
      lib/l10n/localizations_en.dart
  6. 2
      lib/l10n/localizations_zh.dart
  7. 2
      lib/security.dart
  8. 28
      src/apps/domain/layer.rs
  9. 30
      src/apps/domain/models.rs
  10. 78
      src/apps/domain/rpc.rs

57
lib/apps/chat/add.dart

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
@ -44,18 +45,20 @@ class _ChatAddPageState extends State<ChatAddPage> { @@ -44,18 +45,20 @@ class _ChatAddPageState extends State<ChatAddPage> {
if (isOk && app == 'add-friend' && params.length == 3) {
setState(() {
this._showHome = false;
final avatar = Avatar(name: params[2], width: 100.0, colorSurface: false);
this._coreScreen = _InfoScreen(
callback: this._sendCallback,
id: params[0],
addr: params[1],
name: params[2],
bio: ''
bio: '',
avatar: avatar,
);
});
}
}
void _searchCallBack(String id, String addr, String name, String bio) {
void _searchCallBack(String id, String addr, String name, String bio, Avatar avatar) {
setState(() {
this._showHome = false;
this._coreScreen = _InfoScreen(
@ -63,7 +66,8 @@ class _ChatAddPageState extends State<ChatAddPage> { @@ -63,7 +66,8 @@ class _ChatAddPageState extends State<ChatAddPage> {
id: id,
addr: addr,
name: name,
bio: bio
bio: bio,
avatar: avatar,
);
});
}
@ -134,12 +138,14 @@ class _ChatAddPageState extends State<ChatAddPage> { @@ -134,12 +138,14 @@ class _ChatAddPageState extends State<ChatAddPage> {
if (widget.id != '') {
setState(() {
this._showHome = false;
final avatar = Avatar(name: widget.name, width: 100.0, colorSurface: false);
this._coreScreen = _InfoScreen(
callback: this._sendCallback,
name: widget.name,
id: widget.id,
addr: widget.addr,
bio: '',
avatar: avatar,
);
});
}
@ -246,22 +252,37 @@ class _DomainSearchScreenState extends State<_DomainSearchScreen> { @@ -246,22 +252,37 @@ class _DomainSearchScreenState extends State<_DomainSearchScreen> {
params[0].forEach((param) {
final provider = ProviderServer.fromList(param);
if (provider.isDefault) {
_selectedProvider = provider.id;
this._selectedProvider = provider.id;
}
this._providers.add(provider);
});
if (this._selectedProvider == null && this._providers.length > 0) {
this._selectedProvider = this._providers[0].id;
}
setState(() {});
}
_searchResult(List params) {
print(params);
if (params.length == 5) {
String name = params[0].trim();
Avatar avatar = Avatar(name: name, width: 100.0, colorSurface: false);
if (params[4].length > 0) {
avatar = Avatar(
name: name,
avatar: base64.decode(params[4]),
width: 100.0,
colorSurface: false
);
}
widget.callback(
"EHAAAA...AAAAAAA",
'0xaaaaaaa....aaaaaaaaa',
_nameController.text.trim(),
'aaa'
params[1],
params[2],
name,
params[3],
avatar,
);
} else {
setState(() {
@ -309,7 +330,7 @@ class _DomainSearchScreenState extends State<_DomainSearchScreen> { @@ -309,7 +330,7 @@ class _DomainSearchScreenState extends State<_DomainSearchScreen> {
canvasColor: color.surface,
),
child: DropdownButton<int>(
hint: Text(lang.loginChooseAccount, style: TextStyle(fontSize: 16)),
hint: Text('-', style: TextStyle(fontSize: 16)),
iconEnabledColor: Color(0xFFADB0BB),
value: _selectedProvider,
onChanged: (int? m) {
@ -345,10 +366,18 @@ class _DomainSearchScreenState extends State<_DomainSearchScreen> { @@ -345,10 +366,18 @@ class _DomainSearchScreenState extends State<_DomainSearchScreen> {
action: () => setState(() {
final name = this._nameController.text.trim();
if (name.length > 0) {
rpc.send('domain-search', [name]);
String addr = '';
this._providers.forEach((v) {
if (v.id == this._selectedProvider) {
addr = v.addr;
}
});
if (addr.length > 0) {
rpc.send('domain-search', [addr, name]);
this._waiting = true;
this._searchNone = false;
}
}
}), text: this._waiting ? lang.waiting : lang.search, width: 600.0),
]
);
@ -439,6 +468,7 @@ class _InfoScreen extends StatelessWidget { @@ -439,6 +468,7 @@ class _InfoScreen extends StatelessWidget {
final String addr;
final String name;
final String bio;
final Avatar avatar;
const _InfoScreen({
Key? key,
@ -447,6 +477,7 @@ class _InfoScreen extends StatelessWidget { @@ -447,6 +477,7 @@ class _InfoScreen extends StatelessWidget {
required this.addr,
required this.name,
required this.bio,
required this.avatar,
}) : super(key: key);
@override
@ -463,7 +494,7 @@ class _InfoScreen extends StatelessWidget { @@ -463,7 +494,7 @@ class _InfoScreen extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Avatar(name: this.name, width: 100.0, colorSurface: false),
avatar,
Padding(
padding: const EdgeInsets.symmetric(vertical: 10.0),
child: Text(this.name, style: TextStyle(fontWeight: FontWeight.bold)),

9
lib/apps/domain/models.dart

@ -7,6 +7,15 @@ class ProviderServer { @@ -7,6 +7,15 @@ class ProviderServer {
bool isProxy;
bool isActived;
ProviderServer.empty():
this.id = 0,
this.name = '',
this.addr = '',
this.isOk = false,
this.isDefault = false,
this.isProxy = false,
this.isActived = false;
ProviderServer.fromList(List params):
this.id = params[0],
this.name = params[1],

88
lib/apps/domain/page.dart

@ -46,10 +46,20 @@ class _DomainDetailState extends State<DomainDetail> { @@ -46,10 +46,20 @@ class _DomainDetailState extends State<DomainDetail> {
_domainProviderAdd(List params) {
setState(() {
this._listHome = true;
this._showProviders = true;
this._providers[params[0]] = ProviderServer.fromList(params);
});
}
_domainRegisterSuccess(List params) {
setState(() {
this._listHome = true;
this._showProviders = false;
this._names.add(Name.fromList(params));
});
}
@override
void initState() {
super.initState();
@ -57,6 +67,7 @@ class _DomainDetailState extends State<DomainDetail> { @@ -57,6 +67,7 @@ class _DomainDetailState extends State<DomainDetail> {
// resigter rpc for current page.
rpc.addListener('domain-list', _domainList, false);
rpc.addListener('domain-provider-add', _domainProviderAdd, false);
rpc.addListener('domain-register-success', _domainRegisterSuccess, false);
rpc.send('domain-list', []);
}
@ -68,7 +79,7 @@ class _DomainDetailState extends State<DomainDetail> { @@ -68,7 +79,7 @@ class _DomainDetailState extends State<DomainDetail> {
return Scaffold(
appBar: AppBar(
title: Text(lang.domain + ' (${lang.wip})'),
title: Text(lang.domain),
bottom: PreferredSize(
child: Container(color: const Color(0x40ADB0BB), height: 1.0),
preferredSize: Size.fromHeight(1.0)
@ -95,7 +106,9 @@ class _DomainDetailState extends State<DomainDetail> { @@ -95,7 +106,9 @@ class _DomainDetailState extends State<DomainDetail> {
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: this._listHome
? (this._showProviders ? _ListProviderScreen(this._providers) : _ListNameScreen(this._providers, this._names))
: (this._showProviders ? _AddProviderScreen() : _RegisterScreen()),
: ((!this._showProviders && this._providers.length > 0)
? _RegisterScreen(this._providers.values.toList().asMap()) : _AddProviderScreen()
),
))),
floatingActionButton: FloatingActionButton(
onPressed: () => setState(() {
@ -207,7 +220,8 @@ class _ListProviderScreen extends StatelessWidget { @@ -207,7 +220,8 @@ class _ListProviderScreen extends StatelessWidget {
}
class _RegisterScreen extends StatefulWidget {
const _RegisterScreen({Key? key}) : super(key: key);
final Map<int, ProviderServer> providers;
const _RegisterScreen(this.providers);
@override
_RegisterScreenState createState() => _RegisterScreenState();
@ -215,8 +229,9 @@ class _RegisterScreen extends StatefulWidget { @@ -215,8 +229,9 @@ class _RegisterScreen extends StatefulWidget {
class _RegisterScreenState extends State<_RegisterScreen> {
bool _showProviders = false;
List _providers = [''];
int _providerSelected = 0;
int _providerSelected = -1;
bool _registerNone = false;
bool _waiting = false;
TextEditingController _nameController = TextEditingController();
TextEditingController _bioController = TextEditingController();
@ -224,13 +239,35 @@ class _RegisterScreenState extends State<_RegisterScreen> { @@ -224,13 +239,35 @@ class _RegisterScreenState extends State<_RegisterScreen> {
FocusNode _nameFocus = FocusNode();
FocusNode _bioFocus = FocusNode();
_domainRegisterFailure(List _params) {
setState(() {
this._waiting = false;
this._registerNone = true;
});
}
@override
void initState() {
super.initState();
rpc.addListener('domain-register-failure', _domainRegisterFailure, false);
}
@override
Widget build(BuildContext context) {
final color = Theme.of(context).colorScheme;
final lang = AppLocalizations.of(context);
this._providers = ["domain.esse", "eth.esse", "btc.esse"];
final maxIndex = this._providers.length - 1;
if (this._providerSelected < 0) {
this._providerSelected = 0;
widget.providers.forEach((k, v) {
if (v.isDefault) {
this._providerSelected = k;
}
});
}
final maxIndex = widget.providers.length - 1;
return Column(
children: [
@ -249,7 +286,9 @@ class _RegisterScreenState extends State<_RegisterScreen> { @@ -249,7 +286,9 @@ class _RegisterScreenState extends State<_RegisterScreen> {
Expanded(
child: Center(
child: Text(
this._providers[this._providerSelected],
widget.providers.length >= this._providerSelected
? widget.providers[this._providerSelected]!.name
: '',
style: TextStyle(fontWeight: FontWeight.bold)),
)),
TextButton(child: Icon(Icons.navigate_next),
@ -275,15 +314,32 @@ class _RegisterScreenState extends State<_RegisterScreen> { @@ -275,15 +314,32 @@ class _RegisterScreenState extends State<_RegisterScreen> {
controller: _bioController,
focus: _bioFocus),
),
const SizedBox(height: 20.0),
ButtonText(action: () {}, text: lang.send),
SizedBox(
height: 40.0,
child: Center(child: Text(this._registerNone ? lang.domainRegisterFailure : '',
style: TextStyle(color: Colors.red))),
),
ButtonText(
enable: !this._waiting,
action: () {
String name = _nameController.text.trim();
String bio = _bioController.text.trim();
if (name.length > 0 && widget.providers.length >= this._providerSelected) {
final provider = widget.providers[this._providerSelected]!.id;
final addr = widget.providers[this._providerSelected]!.addr;
rpc.send('domain-register', [provider, addr, name, bio]);
setState(() {
this._waiting = true;
});
}
}, text: this._waiting ? lang.waiting : lang.send),
]
);
}
}
class _AddProviderScreen extends StatefulWidget {
const _AddProviderScreen({Key? key}) : super(key: key);
const _AddProviderScreen();
@override
_AddProviderScreenState createState() => _AddProviderScreenState();
@ -292,6 +348,7 @@ class _AddProviderScreen extends StatefulWidget { @@ -292,6 +348,7 @@ class _AddProviderScreen extends StatefulWidget {
class _AddProviderScreenState extends State<_AddProviderScreen> {
TextEditingController _addrController = TextEditingController();
FocusNode _addrFocus = FocusNode();
bool _waiting = false;
@override
Widget build(BuildContext context) {
@ -312,13 +369,18 @@ class _AddProviderScreenState extends State<_AddProviderScreen> { @@ -312,13 +369,18 @@ class _AddProviderScreenState extends State<_AddProviderScreen> {
controller: _addrController,
focus: _addrFocus),
),
ButtonText(action: () {
ButtonText(
enable: !this._waiting,
action: () {
String addr = _addrController.text.trim();
if (addr.substring(0, 2) == '0x') {
addr = addr.substring(2);
}
rpc.send('domain-provider-add', [addr]);
}, text: lang.send),
setState(() {
this._waiting = true;
});
}, text: this._waiting ? lang.waiting : lang.send),
]
);
}

1
lib/l10n/localizations.dart

@ -215,6 +215,7 @@ abstract class AppLocalizations { @@ -215,6 +215,7 @@ abstract class AppLocalizations {
String get domainProviderAdress;
String get domainAddProvider;
String get domainSearch;
String get domainRegisterFailure;
}
class _AppLocalizationsDelegate

2
lib/l10n/localizations_en.dart

@ -334,4 +334,6 @@ class AppLocalizationsEn extends AppLocalizations { @@ -334,4 +334,6 @@ class AppLocalizationsEn extends AppLocalizations {
String get domainAddProvider => 'Add new provider';
@override
String get domainSearch => 'Domain Search';
@override
String get domainRegisterFailure => 'name already existed!';
}

2
lib/l10n/localizations_zh.dart

@ -334,4 +334,6 @@ class AppLocalizationsZh extends AppLocalizations { @@ -334,4 +334,6 @@ class AppLocalizationsZh extends AppLocalizations {
String get domainAddProvider => '添加新的服务商';
@override
String get domainSearch => '域名搜索';
@override
String get domainRegisterFailure => '用户名已存在!';
}

2
lib/security.dart

@ -103,7 +103,7 @@ class _SecurityPageState extends State<SecurityPage> { @@ -103,7 +103,7 @@ class _SecurityPageState extends State<SecurityPage> {
const SizedBox(height: 80.0),
loginForm(color, lang),
const SizedBox(height: 20.0),
ButtonText(text: lang.ok, enable: _accountsLoaded,
ButtonText(width: 450.0, text: lang.ok, enable: _accountsLoaded,
action: () => loginAction(lang.verifyPin)),
Padding(
padding: const EdgeInsets.only(top: 20),

28
src/apps/domain/layer.rs

@ -22,7 +22,7 @@ pub(crate) async fn handle( @@ -22,7 +22,7 @@ pub(crate) async fn handle(
ogid: GroupId,
msg: RecvType,
) -> Result<HandleResult> {
let results = HandleResult::new();
let mut results = HandleResult::new();
match msg {
RecvType::Connect(..)
@ -34,7 +34,7 @@ pub(crate) async fn handle( @@ -34,7 +34,7 @@ pub(crate) async fn handle(
}
RecvType::Event(addr, bytes) => {
// server & client handle it.
let LayerServerEvent(event, proof) = bincode::deserialize(&bytes)?;
let LayerServerEvent(event, _proof) = bincode::deserialize(&bytes)?;
let db = domain_db(layer.read().await.base(), &ogid)?;
@ -46,24 +46,28 @@ pub(crate) async fn handle( @@ -46,24 +46,28 @@ pub(crate) async fn handle(
);
let mut provider = Provider::get_by_addr(&db, &addr)?;
provider.ok(&db, name, support_request);
// TODO UI: add new provider.
provider.ok(&db, name, support_request)?;
results.rpcs.push(rpc::add_provider(ogid, &provider));
}
ServerEvent::Result(name, is_ok) => {
let provider = Provider::get_by_addr(&db, &addr)?;
let mut name = Name::get_by_name_provider(&db, &name, &provider.id)?;
let mut user = Name::get_by_name_provider(&db, &name, &provider.id)?;
if is_ok {
//name.ok(&db);
Name::active(&db, &user.id, true)?;
user.is_ok = true;
user.is_actived = true;
results.rpcs.push(rpc::register_success(ogid, &user));
} else {
//name.delete(&db);
Name::delete(&db, &user.id)?;
results.rpcs.push(rpc::register_failure(ogid, &name));
}
// TODO UI: add new regsiter name.
}
ServerEvent::Info(_uname, _ugid, _uaddr, _ubio, _uavatar) => {
// TODO UI: show search result.
ServerEvent::Info(uname, ugid, uaddr, ubio, uavatar) => {
println!("------ Search: {} --", uname);
results.rpcs.push(rpc::search_result(
ogid, &uname, &ugid, &uaddr, &ubio, &uavatar,
));
}
ServerEvent::None(_name) => {
// TODO UI: show search result.

30
src/apps/domain/models.rs

@ -159,20 +159,31 @@ impl Provider { @@ -159,20 +159,31 @@ impl Provider {
/// Name Model.
pub(crate) struct Name {
/// db auto-increment id.
id: i64,
pub id: i64,
/// provider database id.
provider: i64,
/// name.
name: String,
pub name: String,
/// bio.
bio: String,
pub bio: String,
/// is add ok.
is_ok: bool,
pub is_ok: bool,
/// is actived.
is_actived: bool,
pub is_actived: bool,
}
impl Name {
pub fn prepare(name: String, bio: String, provider: i64) -> Self {
Self {
name,
bio,
provider,
is_ok: false,
is_actived: false,
id: 0,
}
}
pub fn to_rpc(&self) -> RpcParam {
json!([
self.id,
@ -197,7 +208,9 @@ impl Name { @@ -197,7 +208,9 @@ impl Name {
/// use in rpc when load providers.
pub fn list(db: &DStorage) -> Result<Vec<Self>> {
let matrix = db.query("SELECT id, provider, name, bio, is_ok, is_actived FROM names")?;
let matrix = db.query(
"SELECT id, provider, name, bio, is_ok, is_actived FROM names WHERE is_ok = true",
)?;
let mut names = vec![];
for values in matrix {
names.push(Self::from_values(values));
@ -270,7 +283,10 @@ impl Name { @@ -270,7 +283,10 @@ impl Name {
/// active/suspend the name.
pub fn active(db: &DStorage, id: &i64, active: bool) -> Result<()> {
let sql = format!("UPDATE names SET is_actived = {} WHERE id = {}", active, id);
let sql = format!(
"UPDATE names SET is_ok = true, is_actived = {} WHERE id = {}",
active, id
);
db.update(&sql)?;
Ok(())
}

78
src/apps/domain/rpc.rs

@ -2,7 +2,7 @@ use std::sync::Arc; @@ -2,7 +2,7 @@ use std::sync::Arc;
use tdn::types::{
group::GroupId,
primitive::{HandleResult, PeerAddr},
rpc::{json, RpcError, RpcHandler, RpcParam},
rpc::{json, rpc_response, RpcError, RpcHandler, RpcParam},
};
use domain_types::PeerEvent;
@ -13,6 +13,48 @@ use super::{ @@ -13,6 +13,48 @@ use super::{
};
use crate::{rpc::RpcState, storage::domain_db};
#[inline]
pub(crate) fn add_provider(mgid: GroupId, provider: &Provider) -> RpcParam {
rpc_response(0, "domain-provider-add", json!(provider.to_rpc()), mgid)
}
#[inline]
pub(crate) fn register_success(mgid: GroupId, name: &Name) -> RpcParam {
rpc_response(0, "domain-register-success", json!(name.to_rpc()), mgid)
}
#[inline]
pub(crate) fn register_failure(mgid: GroupId, name: &str) -> RpcParam {
rpc_response(0, "domain-register-failure", json!([name]), mgid)
}
#[inline]
pub(crate) fn search_result(
mgid: GroupId,
name: &str,
gid: &GroupId,
addr: &PeerAddr,
bio: &str,
avatar: &Vec<u8>,
) -> RpcParam {
rpc_response(
0,
"domain-search",
json!([
name,
gid.to_hex(),
addr.to_hex(),
bio,
if avatar.len() > 0 {
base64::encode(avatar)
} else {
"".to_owned()
}
]),
mgid,
)
}
pub(crate) fn new_rpc_handler(handler: &mut RpcHandler<RpcState>) {
handler.add_method(
"domain-list",
@ -66,17 +108,23 @@ pub(crate) fn new_rpc_handler(handler: &mut RpcHandler<RpcState>) { @@ -66,17 +108,23 @@ pub(crate) fn new_rpc_handler(handler: &mut RpcHandler<RpcState>) {
handler.add_method(
"domain-register",
|gid: GroupId, params: Vec<RpcParam>, state: Arc<RpcState>| async move {
let _provider = params[0].as_i64().ok_or(RpcError::ParseError)?;
let _symbol = params[1].as_str().ok_or(RpcError::ParseError)?.to_string();
let _bio = params[2].as_str().ok_or(RpcError::ParseError)?.to_string();
let provider = params[0].as_i64().ok_or(RpcError::ParseError)?;
let addr = PeerAddr::from_hex(params[1].as_str().ok_or(RpcError::ParseError)?)?;
let name = params[2].as_str().ok_or(RpcError::ParseError)?.to_string();
let bio = params[3].as_str().ok_or(RpcError::ParseError)?.to_string();
let _me = state.group.read().await.clone_user(&gid)?;
let me = state.group.read().await.clone_user(&gid)?;
// Send to remote domain service.
//
// save to db.
let mut results = HandleResult::new();
let db = domain_db(state.layer.read().await.base(), &gid)?;
let mut u = Name::prepare(name, bio, provider);
u.insert(&db)?;
Ok(HandleResult::rpc(json!(params)))
// send to server.
let event = PeerEvent::Register(u.name, u.bio, me.avatar);
add_layer(&mut results, addr, event, gid)?;
Ok(results)
},
);
@ -100,10 +148,16 @@ pub(crate) fn new_rpc_handler(handler: &mut RpcHandler<RpcState>) { @@ -100,10 +148,16 @@ pub(crate) fn new_rpc_handler(handler: &mut RpcHandler<RpcState>) {
handler.add_method(
"domain-search",
|_gid: GroupId, params: Vec<RpcParam>, _state: Arc<RpcState>| async move {
let _name = params[0].as_str().ok_or(RpcError::ParseError)?;
|gid: GroupId, params: Vec<RpcParam>, _state: Arc<RpcState>| async move {
let addr = PeerAddr::from_hex(params[0].as_str().ok_or(RpcError::ParseError)?)?;
let name = params[1].as_str().ok_or(RpcError::ParseError)?.to_owned();
Ok(HandleResult::rpc(json!(params)))
let mut results = HandleResult::new();
// send to server.
let event = PeerEvent::Search(name);
add_layer(&mut results, addr, event, gid)?;
Ok(results)
},
);
}

Loading…
Cancel
Save