diff --git a/assets/logo/logo_domain.png b/assets/logo/logo_domain.png new file mode 100644 index 0000000..8324e9c Binary files /dev/null and b/assets/logo/logo_domain.png differ diff --git a/lib/apps/chat/add.dart b/lib/apps/chat/add.dart index 5ce1a26..318266c 100644 --- a/lib/apps/chat/add.dart +++ b/lib/apps/chat/add.dart @@ -138,7 +138,9 @@ class _ChatAddPageState extends State { UserInfo(app: 'add-friend', id: account.id, name: account.name, addr: Global.addr) ), - child: Text(lang.myQrcode, style: TextStyle(fontSize: 16.0)), + child: Padding( + padding: const EdgeInsets.only(right: 10.0), + child: Text(lang.myQrcode, style: TextStyle(fontSize: 16.0))), ), ] ), diff --git a/lib/apps/device/page.dart b/lib/apps/device/page.dart index b969766..f6ce808 100644 --- a/lib/apps/device/page.dart +++ b/lib/apps/device/page.dart @@ -46,7 +46,6 @@ class _DevicesPageState extends State { } }, text: lang.send, - width: 600.0 ), ] )); diff --git a/lib/apps/domain/page.dart b/lib/apps/domain/page.dart index e69de29..75a5bd9 100644 --- a/lib/apps/domain/page.dart +++ b/lib/apps/domain/page.dart @@ -0,0 +1,284 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import 'package:esse/utils/adaptive.dart'; +import 'package:esse/utils/pick_image.dart'; +import 'package:esse/utils/pick_file.dart'; +import 'package:esse/l10n/localizations.dart'; +import 'package:esse/widgets/emoji.dart'; +import 'package:esse/widgets/button_text.dart'; +import 'package:esse/widgets/input_text.dart'; +import 'package:esse/widgets/shadow_dialog.dart'; +import 'package:esse/widgets/audio_recorder.dart'; +import 'package:esse/widgets/show_contact.dart'; +import 'package:esse/global.dart'; +import 'package:esse/options.dart'; + +//import 'package:esse/apps/assistant/models.dart'; +//import 'package:esse/apps/assistant/provider.dart'; + +class DomainDetail extends StatefulWidget { + const DomainDetail({Key? key}) : super(key: key); + + @override + _DomainDetailState createState() => _DomainDetailState(); +} + +class _DomainDetailState extends State { + bool _showProviders = false; + bool _listHome = true; + + @override + Widget build(BuildContext context) { + final color = Theme.of(context).colorScheme; + final lang = AppLocalizations.of(context); + + return Scaffold( + appBar: AppBar( + title: Text(lang.domain + ' (${lang.wip})'), + bottom: PreferredSize( + child: Container(color: const Color(0x40ADB0BB), height: 1.0), + preferredSize: Size.fromHeight(1.0) + ), + actions: [ + TextButton( + onPressed: () { + this._listHome = true; + this._showProviders = !this._showProviders; + setState(() {}); + }, + child: Padding( + padding: const EdgeInsets.only(right: 10.0), + child: Text(this._showProviders ? lang.domainShowName : lang.domainShowProvider) + ) + ), + ] + ), + body: Container( + padding: const EdgeInsets.all(10.0), + alignment: Alignment.topCenter, + child: SingleChildScrollView( + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 20.0), + child: this._listHome + ? (this._showProviders ? _ListProviderScreen() : _ListNameScreen()) + : (this._showProviders ? _AddProviderScreen() : _RegisterScreen()), + ))), + floatingActionButton: FloatingActionButton( + onPressed: () => setState(() { + this._listHome = !this._listHome; + } + ), + child: Icon(this._listHome ? Icons.add : Icons.arrow_back, color: Colors.white), + backgroundColor: Color(0xFF6174FF), + ), + ); + } +} + +class _ListNameScreen extends StatelessWidget { + const _ListNameScreen({Key? key}) : super(key: key); + + Widget _nameItem(int id, String name, String provider, bool isActive, ColorScheme color) { + return Card( + elevation: 0.0, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)), + margin: new EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0), + child: Container( + decoration: BoxDecoration(color: color.surface, borderRadius: BorderRadius.circular(15.0)), + child: ListTile( + contentPadding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0), + leading: Container( + padding: EdgeInsets.only(right: 12.0), + decoration: new BoxDecoration( + border: new Border(right: new BorderSide(width: 1.0, color: Color(0xA0ADB0BB)))), + child: isActive ? Icon(Icons.toggle_on, color: color.primary) : Icon(Icons.toggle_off), + ), + title: Text(name, style: TextStyle(fontWeight: FontWeight.bold)), + subtitle: Row( + children: [ + Expanded(child: Text(provider)), + ], + ), + trailing: Icon(Icons.keyboard_arrow_right, size: 30.0), + ) + ), + ); + } + + @override + Widget build(BuildContext context) { + final color = Theme.of(context).colorScheme; + + return Column( + children: [ + _nameItem(0, "Sun", "domain.esse", true, color), + _nameItem(0, "Huachuang", "domain.esse", false, color), + _nameItem(0, "sun", "eth.esse", true, color), + ] + ); + } +} + +class _ListProviderScreen extends StatelessWidget { + const _ListProviderScreen({Key? key}) : super(key: key); + + Widget _providerItem(int id, String name, String address, bool isDefault, ColorScheme color, AppLocalizations lang) { + return Card( + elevation: 0.0, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)), + margin: new EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0), + child: Container( + decoration: BoxDecoration(color: color.surface, borderRadius: BorderRadius.circular(15.0)), + child: ListTile( + contentPadding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0), + leading: Container( + padding: EdgeInsets.only(right: 12.0), + decoration: new BoxDecoration( + border: new Border( + right: new BorderSide(width: 1.0, color: Color(0xA0ADB0BB)))), + child: Icon(Icons.sync), + ), + title: Text(name, style: TextStyle(fontWeight: FontWeight.bold)), + subtitle: Row( + children: [ + Expanded(child: Text(address)), + ], + ), + trailing: Row( + mainAxisSize: MainAxisSize.min, + children: [ + if (isDefault) Text(lang.default0, style: TextStyle(color: color.primary)), + Icon(Icons.keyboard_arrow_right, size: 30.0), + ] + ) + ) + ), + ); + } + + @override + Widget build(BuildContext context) { + final color = Theme.of(context).colorScheme; + final lang = AppLocalizations.of(context); + + return Column( + children: [ + _providerItem(0, "domain.esse", "0x89d240...77407b0e", true, color, lang), + _providerItem(0, "eth.esse", "0x89d240...77407b0e", false, color, lang), + ] + ); + } +} + +class _RegisterScreen extends StatefulWidget { + const _RegisterScreen({Key? key}) : super(key: key); + + @override + _RegisterScreenState createState() => _RegisterScreenState(); +} + +class _RegisterScreenState extends State<_RegisterScreen> { + bool _showProviders = false; + List _providers = ['']; + int _providerSelected = 0; + + TextEditingController _nameController = TextEditingController(); + TextEditingController _bioController = TextEditingController(); + + FocusNode _nameFocus = FocusNode(); + FocusNode _bioFocus = FocusNode(); + + @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; + + return Column( + children: [ + Container( + padding: EdgeInsets.symmetric(vertical: 10.0), + height: 60.0, + width: 600.0, + child: Row( + mainAxisSize: MainAxisSize.max, + children: [ + TextButton(child: Icon(Icons.navigate_before), + onPressed: this._providerSelected > 0 ? () => setState(() { + this._providerSelected = this._providerSelected - 1; + }) : null, + ), + Expanded( + child: Center( + child: Text( + this._providers[this._providerSelected], + style: TextStyle(fontWeight: FontWeight.bold)), + )), + TextButton(child: Icon(Icons.navigate_next), + onPressed: this._providerSelected < maxIndex ? () => setState(() { + this._providerSelected = this._providerSelected + 1; + }) : null, + ), + ] + )), + Container( + padding: EdgeInsets.symmetric(vertical: 10.0), + child: InputText( + icon: Icons.account_box, + text: lang.domainName, + controller: _nameController, + focus: _nameFocus), + ), + Container( + padding: EdgeInsets.symmetric(vertical: 10.0), + child: InputText( + icon: Icons.campaign, + text: lang.bio, + controller: _bioController, + focus: _bioFocus), + ), + const SizedBox(height: 20.0), + ButtonText(action: () {}, text: lang.send), + ] + ); + } +} + +class _AddProviderScreen extends StatefulWidget { + const _AddProviderScreen({Key? key}) : super(key: key); + + @override + _AddProviderScreenState createState() => _AddProviderScreenState(); +} + +class _AddProviderScreenState extends State<_AddProviderScreen> { + TextEditingController _addrController = TextEditingController(); + FocusNode _addrFocus = FocusNode(); + + @override + Widget build(BuildContext context) { + final color = Theme.of(context).colorScheme; + final lang = AppLocalizations.of(context); + + return Column( + children: [ + Container( + padding: EdgeInsets.symmetric(vertical: 10.0), + child: Text(lang.domainAddProvider, style: TextStyle(fontWeight: FontWeight.bold)), + ), + Container( + padding: EdgeInsets.symmetric(vertical: 30.0), + child: InputText( + icon: Icons.location_on, + text: lang.address, + controller: _addrController, + focus: _addrFocus), + ), + ButtonText(action: () {}, text: lang.send), + ] + ); + } +} diff --git a/lib/apps/group_chat/add.dart b/lib/apps/group_chat/add.dart index 6e723e6..25ddc02 100644 --- a/lib/apps/group_chat/add.dart +++ b/lib/apps/group_chat/add.dart @@ -231,7 +231,9 @@ class _GroupAddPageState extends State { onPressed: () => Navigator.push(context, MaterialPageRoute(builder: (context) => QRScan(callback: _scanCallback)) ), - child: Text(lang.scanQr, style: TextStyle(fontSize: 16.0)), + child: Padding( + padding: const EdgeInsets.only(right: 10.0), + child: Text(lang.scanQr, style: TextStyle(fontSize: 16.0))), ), ], bottom: TabBar( @@ -278,7 +280,7 @@ class _GroupAddPageState extends State { controller: _joinAddrController, focus: _joinAddrFocus), const SizedBox(height: 20.0), - ButtonText(action: _join, text: lang.send, width: 600.0), + ButtonText(action: _join, text: lang.send), const SizedBox(height: 20.0), const Divider(height: 1.0, color: Color(0x40ADB0BB)), const SizedBox(height: 10.0), @@ -517,7 +519,7 @@ class _GroupAddPageState extends State { ), ), const SizedBox(height: 20.0), - ButtonText(action: _create, text: lang.create, width: 600.0), + ButtonText(action: _create, text: lang.create), const SizedBox(height: 20.0), const Divider(height: 1.0, color: Color(0x40ADB0BB)), const SizedBox(height: 10.0), diff --git a/lib/apps/service/list.dart b/lib/apps/service/list.dart index 95457a9..da4a6c2 100644 --- a/lib/apps/service/list.dart +++ b/lib/apps/service/list.dart @@ -12,6 +12,7 @@ const List INNER_SERVICES = [ InnerService.Files, InnerService.Assistant, InnerService.GroupChat, + InnerService.Domain, ]; class ServiceList extends StatefulWidget { diff --git a/lib/apps/service/models.dart b/lib/apps/service/models.dart index a7cb844..a735eff 100644 --- a/lib/apps/service/models.dart +++ b/lib/apps/service/models.dart @@ -4,11 +4,13 @@ import 'package:esse/l10n/localizations.dart'; import 'package:esse/apps/assistant/page.dart'; import 'package:esse/apps/file/list.dart'; import 'package:esse/apps/group_chat/list.dart'; +import 'package:esse/apps/domain/page.dart'; enum InnerService { Files, Assistant, GroupChat, + Domain, } extension InnerServiceExtension on InnerService { @@ -20,6 +22,8 @@ extension InnerServiceExtension on InnerService { return [lang.assistant, lang.assistantBio, 'assets/logo/logo_assistant.png']; case InnerService.GroupChat: return [lang.groupChat, lang.groupChatIntro, 'assets/logo/logo_group_chat.png']; + case InnerService.Domain: + return [lang.domain, lang.domainIntro, 'assets/logo/logo_domain.png']; } } @@ -31,6 +35,8 @@ extension InnerServiceExtension on InnerService { return AssistantDetail(); case InnerService.GroupChat: return GroupChatList(); + case InnerService.Domain: + return DomainDetail(); } } } diff --git a/lib/l10n/localizations.dart b/lib/l10n/localizations.dart index 338bcc3..565bd18 100644 --- a/lib/l10n/localizations.dart +++ b/lib/l10n/localizations.dart @@ -57,6 +57,7 @@ abstract class AppLocalizations { String get onlineSuspend; String get onlineLost; String get nickname; + String get bio; String get id; String get address; String get remark; @@ -90,6 +91,7 @@ abstract class AppLocalizations { String get invite; String get emoji; String get record; + String get default0; String get others; String get closed; @@ -171,8 +173,10 @@ abstract class AppLocalizations { // services String get files; String get filesBio; + String get assistant; String get assistantBio; + String get groupChat; String get groupChats; String get groupChatAdd; @@ -198,6 +202,14 @@ abstract class AppLocalizations { String get groupCheckTypeDeny; String get members; String get groupRequireConsent; + + String get domain; + String get domainIntro; + String get domainShowProvider; + String get domainShowName; + String get domainName; + String get domainProviderAdress; + String get domainAddProvider; } class _AppLocalizationsDelegate diff --git a/lib/l10n/localizations_en.dart b/lib/l10n/localizations_en.dart index aecfb61..6a9b0c0 100644 --- a/lib/l10n/localizations_en.dart +++ b/lib/l10n/localizations_en.dart @@ -39,6 +39,8 @@ class AppLocalizationsEn extends AppLocalizations { @override String get nickname => 'Name'; @override + String get bio => 'Bio'; + @override String get id => 'ID'; @override String get address => 'Address'; @@ -105,6 +107,8 @@ class AppLocalizationsEn extends AppLocalizations { @override String get record => 'Record'; @override + String get default0 => 'Default'; + @override String get others => 'Others'; @override String get closed => 'Closed'; @@ -306,4 +310,18 @@ class AppLocalizationsEn extends AppLocalizations { String get members => 'Members'; @override String get groupRequireConsent => "Requires manager's consent"; + @override + String get domain => 'Domain'; + @override + String get domainIntro => 'Unique identity to global'; + @override + String get domainShowProvider => 'show all providers'; + @override + String get domainShowName => 'show all names'; + @override + String get domainName => 'Username'; + @override + String get domainProviderAdress => 'Provider Network Address'; + @override + String get domainAddProvider => 'Add new provider'; } diff --git a/lib/l10n/localizations_zh.dart b/lib/l10n/localizations_zh.dart index 2d56878..7c59376 100644 --- a/lib/l10n/localizations_zh.dart +++ b/lib/l10n/localizations_zh.dart @@ -39,6 +39,8 @@ class AppLocalizationsZh extends AppLocalizations { @override String get nickname => '昵称'; @override + String get bio => '个性签名'; + @override String get id => '身份账户'; @override String get address => '网络地址'; @@ -105,6 +107,8 @@ class AppLocalizationsZh extends AppLocalizations { @override String get record => '语音'; @override + String get default0 => '默认'; + @override String get others => '其他'; @override String get closed => '已关闭'; @@ -306,4 +310,18 @@ class AppLocalizationsZh extends AppLocalizations { String get members => '成员'; @override String get groupRequireConsent => "需要管理员同意"; + @override + String get domain => '分布式域名'; + @override + String get domainIntro => '管理自己的公开身份'; + @override + String get domainShowProvider => '展示所有服务商'; + @override + String get domainShowName => '展示所有注册名'; + @override + String get domainName => '用户名'; + @override + String get domainProviderAdress => '服务商网络地址'; + @override + String get domainAddProvider => '添加新的服务商'; } diff --git a/lib/pages/account_generate.dart b/lib/pages/account_generate.dart index 42c108b..2adfdf7 100644 --- a/lib/pages/account_generate.dart +++ b/lib/pages/account_generate.dart @@ -214,6 +214,7 @@ class _AccountGeneratePageState extends State { ), const SizedBox(height: 32.0), ButtonText( + width: 450, text: lang.next, enable: _mnemonicChecked, action: () { @@ -270,7 +271,7 @@ class _AccountGeneratePageState extends State { }), ), const SizedBox(height: 32.0), - ButtonText(text: lang.ok, action: () => registerNewAction(lang.setPin), + ButtonText(width: 450, text: lang.ok, action: () => registerNewAction(lang.setPin), enable: this._registerChecked), _footer(lang.hasAccount, () => Navigator.of(context).pop()), ]) diff --git a/lib/pages/account_restore.dart b/lib/pages/account_restore.dart index 4713180..5aad393 100644 --- a/lib/pages/account_restore.dart +++ b/lib/pages/account_restore.dart @@ -274,6 +274,7 @@ class _AccountRestorePageState extends State { ])), const SizedBox(height: 32.0), ButtonText( + width: 450, text: lang.next, enable: _statusChecked, action: () => _mnemonicRegister(lang.unknown, lang.setPin), diff --git a/lib/widgets/button_text.dart b/lib/widgets/button_text.dart index fdb0482..2a12de4 100644 --- a/lib/widgets/button_text.dart +++ b/lib/widgets/button_text.dart @@ -12,7 +12,7 @@ class ButtonText extends StatelessWidget { Key? key, required this.action, this.text = '', - this.width = 450.0, + this.width = 600.0, this.height = 50.0, this.enable = true, }) : super(key: key); diff --git a/pubspec.yaml b/pubspec.yaml index 48c6ea4..5dcc726 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -74,6 +74,7 @@ flutter: - assets/logo/logo_assistant.png - assets/logo/logo_files.png - assets/logo/logo_group_chat.png + - assets/logo/logo_domain.png - assets/images/background_light.jpg - assets/images/background_dark.jpg - assets/images/image_missing.png diff --git a/src/apps/domain/mod.rs b/src/apps/domain/mod.rs index 6968310..6bc0334 100644 --- a/src/apps/domain/mod.rs +++ b/src/apps/domain/mod.rs @@ -1,6 +1,8 @@ +use std::sync::Arc; use tdn::types::{ - primitive::HandleResult, - rpc::{json, RpcHandler}, + group::GroupId, + primitive::{HandleResult, PeerAddr}, + rpc::{json, rpc_response, RpcError, RpcHandler, RpcParam}, }; use crate::rpc::RpcState; @@ -9,4 +11,40 @@ pub(crate) fn new_rpc_handler(handler: &mut RpcHandler) { handler.add_method("domain-echo", |_, params, _| async move { Ok(HandleResult::rpc(json!(params))) }); + + handler.add_method( + "domain-add", + |_gid: GroupId, params: Vec, _state: Arc| async move { + let _provider = PeerAddr::from_hex(params[1].as_str().ok_or(RpcError::ParseError)?)?; + let _name = params[2].as_str().ok_or(RpcError::ParseError)?.to_string(); + + Ok(HandleResult::rpc(json!(params))) + }, + ); + + handler.add_method( + "domain-remove", + |_gid: GroupId, params: Vec, _state: Arc| async move { + let _id = params[0].as_i64().ok_or(RpcError::ParseError)?; + + Ok(HandleResult::rpc(json!(params))) + }, + ); + + handler.add_method( + "domain-register", + |gid: GroupId, params: Vec, state: Arc| async move { + let _provider = PeerAddr::from_hex(params[1].as_str().ok_or(RpcError::ParseError)?)?; + let _symbol = 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)?; + + // Send to remote domain service. + + // + + Ok(HandleResult::rpc(json!(params))) + }, + ); }