diff --git a/lib/pages/login_screen/login_screen.dart b/lib/pages/login_screen/login_screen.dart index 0fc0794..8f13ed8 100644 --- a/lib/pages/login_screen/login_screen.dart +++ b/lib/pages/login_screen/login_screen.dart @@ -1,6 +1,7 @@ import 'package:dart_nostr/dart_nostr.dart'; import 'package:drifter/models/keys.dart'; import 'package:drifter/pages/home_screen/widgets/message_text_button_widget.dart'; +import 'package:drifter/pages/profile_screen/profile_screen.dart'; import 'package:drifter/pages/profile_screen/widgets/keys_option_modal_bottom_sheet.dart'; import 'package:drifter/pages/profile_screen/widgets/message_snack_bar.dart'; @@ -11,30 +12,16 @@ import 'package:flutter/material.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:nostr_tools/nostr_tools.dart'; -class LoginScreen extends StatelessWidget { +class LoginScreen extends StatefulWidget { const LoginScreen({super.key}); - final _secureStorage = const FlutterSecureStorage(); + @override + State createState() => LoginScreenState(); +} - Future addKeyToStorage( - String privateKeyHex, - String publicKeyHex, - String nsecKey, - String npubKey, - ) async { -// Waiting for both write operations to complete - Future.wait([ - _secureStorage.write(key: 'privateKey', value: privateKeyHex), - _secureStorage.write(key: 'publicKey', value: privateKeyHex), - _secureStorage.write(key: 'nsec', value: nsecKey), - _secureStorage.write(key: 'npub', value: npubKey), - ]); - - // Updating status variables and starting widget rebuilding - -// Returns a boolean value indicating whether the keys were successfully added to the repository or not. - return Keys.keysExist; - } +class LoginScreenState extends State { + final keyGenerator = KeyApi(); + final nip19 = Nip19(); @override Widget build(BuildContext context) { @@ -70,8 +57,9 @@ class LoginScreen extends StatelessWidget { bool isValidHexKey = Nostr.instance.keysService.isValidPrivateKey(value); bool isValidNSec = value.trim().startsWith('nsec') && - Nostr.instance.keysService.isValidPrivateKey( - NostrClientUtils.hexEncode(value)['data']); + Nostr.instance.keysService.isValidPrivateKey(Nostr + .instance.keysService + .decodeNsecKeyToPrivateKey(value)); if (!(isValidHexKey || isValidNSec)) { return 'Your private key is not valid.'; } @@ -92,59 +80,68 @@ class LoginScreen extends StatelessWidget { style: ButtonStyle( backgroundColor: MaterialStateProperty.all(AppColors.background)), + child: const Text( + 'Login', + ), onPressed: () { if (formKey.currentState!.validate()) { - // Он получает значение закрытого ключа из _keyController текстового поля и присваивает его переменной privateKeyHex. String privateKeyHex = keyController.text.trim(); String publicKeyHex; String nsecKey; String npubKey; - // Он проверяет, начинается ли строка privateKeyHex со строки « nsec », что указывает на то, что она может быть в формате NIP-19. Если это так, он декодирует метод privateKeyHex using _nip19.decode(privateKeyHex) для получения поля « данные », которое представляет фактический закрытый ключ в шестнадцатеричном формате. + // if (privateKeyHex.startsWith('nsec')) { + // nsecKey = privateKeyHex; + // final decoded = Nostr.instance.keysService + // .decodeNsecKeyToPrivateKey(privateKeyHex); + // privateKeyHex = decoded; + // publicKeyHex = Nostr.instance.keysService + // .derivePublicKey(privateKey: 'privateKeyHex'); + // npubKey = Nostr.instance.keysService + // .encodePublicKeyToNpub(publicKeyHex); + // } else { + // publicKeyHex = Nostr.instance.keysService + // .derivePublicKey(privateKey: 'privateKeyHex'); + // nsecKey = Nostr.instance.keysService + // .encodePrivateKeyToNsec(privateKeyHex); + // npubKey = Nostr.instance.keysService + // .encodePublicKeyToNpub(publicKeyHex); + // } + if (privateKeyHex.startsWith('nsec')) { - nsecKey = privateKeyHex; - final decoded = Nostr.instance.keysService - .decodeNsecKeyToPrivateKey(privateKeyHex); - privateKeyHex = decoded; - publicKeyHex = Nostr.instance.keysService - .derivePublicKey(privateKey: 'privateKeyHex'); - npubKey = Nostr.instance.keysService - .encodePublicKeyToNpub(publicKeyHex); - } - // Если privateKeyHex не начинается с « nsec », это означает, что это обычный шестнадцатеричный закрытый ключ. - else { - publicKeyHex = Nostr.instance.keysService - .derivePublicKey(privateKey: 'privateKeyHex'); - nsecKey = Nostr.instance.keysService - .encodePrivateKeyToNsec(privateKeyHex); - npubKey = Nostr.instance.keysService - .encodePublicKeyToNpub(publicKeyHex); + final decoded = nip19.decode(privateKeyHex); + privateKeyHex = decoded['data']; + publicKeyHex = keyGenerator.getPublicKey(privateKeyHex); + nsecKey = nip19.nsecEncode(privateKeyHex); + npubKey = nip19.npubEncode(publicKeyHex); + } else { + publicKeyHex = keyGenerator.getPublicKey(privateKeyHex); + nsecKey = nip19.nsecEncode(privateKeyHex); + npubKey = nip19.npubEncode(publicKeyHex); } - // Затем он вызывает _addKeysToStorage метод для добавления закрытого ключа и открытого ключа в хранилище. Он прикрепляет then() к этому методу обратный вызов для обработки случая, когда ключи успешно добавлены в хранилище. - addKeyToStorage(privateKeyHex, publicKeyHex, nsecKey, npubKey) + ProfileScreenState() + .addKeyToStorage( + privateKeyHex, publicKeyHex, nsecKey, npubKey) .then((keysAdded) { if (keysAdded) { keyController.clear(); ScaffoldMessenger.of(context).showSnackBar( MessageSnackBar(label: 'Congratulations! Keys Stored!'), ); - setState() { - Keys.privateKey = privateKeyHex; - Keys.publicKey = publicKeyHex; - Keys.nsecKey = nsecKey; - Keys.npubKey = npubKey; - Keys.keysExist = true; - } + // setState() { + // Keys.privateKey = privateKeyHex; + // Keys.publicKey = publicKeyHex; + // Keys.nsecKey = nsecKey; + // Keys.npubKey = npubKey; + // Keys.keysExist = true; + // } } }); } else { formKey.currentState?.setState(() {}); } }, - child: Text( - 'Login', - ), ), ) ], diff --git a/lib/pages/profile_screen/profile_screen.dart b/lib/pages/profile_screen/profile_screen.dart index 3f40f70..c8dc3c1 100644 --- a/lib/pages/profile_screen/profile_screen.dart +++ b/lib/pages/profile_screen/profile_screen.dart @@ -17,7 +17,8 @@ class ProfileScreen extends StatefulWidget { } class ProfileScreenState extends State { - final _secureStorage = const FlutterSecureStorage(); + final secureStorage = const FlutterSecureStorage(); + bool _toHex = false; TextEditingController privateKeyInput = TextEditingController(); TextEditingController publicKeyInput = TextEditingController(); @@ -37,6 +38,7 @@ class ProfileScreenState extends State { final nsec = Nostr.instance.keysService.encodePrivateKeyToNsec(newPrivateKey); + // final nsecDecoded = // Nostr.instance.keysService.decodeNsecKeyToPrivateKey(nsec); // assert(nsecDecoded['type'] == 'nsec'); @@ -47,6 +49,7 @@ class ProfileScreenState extends State { // final newPublicKey = keyGenerator.getPublicKey(newPrivateKey); final npub = Nostr.instance.keysService.encodePublicKeyToNpub(newPublicKey); + // final npubDecoded = // Nostr.instance.keysService.decodeNpubKeyToPublicKey(npub); // assert(npubDecoded['type'] == 'npub'); @@ -57,11 +60,11 @@ class ProfileScreenState extends State { Future _getKeysFromStorage() async { // Reading values associated with the " privateKey " and " publicKey " keys from a secure repository - final storedPrivateKey = await _secureStorage.read(key: 'privateKey'); - final storedPublicKey = await _secureStorage.read(key: 'publicKey'); + final storedPrivateKey = await secureStorage.read(key: 'privateKey'); + final storedPublicKey = await secureStorage.read(key: 'publicKey'); - final storedNsecKey = await _secureStorage.read(key: 'nsec'); - final storedNpubKey = await _secureStorage.read(key: 'npub'); + final storedNsecKey = await secureStorage.read(key: 'nsec'); + final storedNpubKey = await secureStorage.read(key: 'npub'); // Indicates that both private and public keys are stored in a secure repository, after which, the state variables are updated if (storedPrivateKey != null && @@ -88,10 +91,10 @@ class ProfileScreenState extends State { ) async { // Waiting for both write operations to complete Future.wait([ - _secureStorage.write(key: 'privateKey', value: privateKeyHex), - _secureStorage.write(key: 'publicKey', value: publicKeyHex), - _secureStorage.write(key: 'nsec', value: nsecKey), - _secureStorage.write(key: 'npub', value: npubKey), + secureStorage.write(key: 'privateKey', value: privateKeyHex), + secureStorage.write(key: 'publicKey', value: publicKeyHex), + secureStorage.write(key: 'nsec', value: nsecKey), + secureStorage.write(key: 'npub', value: npubKey), ]); // Updating status variables and starting widget rebuilding @@ -110,10 +113,10 @@ class ProfileScreenState extends State { Future _deleteKeysStorage() async { // Calling secure storage to remove keys from storage Future.wait([ - _secureStorage.delete(key: 'privateKey'), - _secureStorage.delete(key: 'publicKey'), - _secureStorage.delete(key: 'nsec'), - _secureStorage.delete(key: 'npub'), + secureStorage.delete(key: 'privateKey'), + secureStorage.delete(key: 'publicKey'), + secureStorage.delete(key: 'nsec'), + secureStorage.delete(key: 'npub'), ]); // Updating status variables, resetting values after deleting keys from the repository @@ -128,42 +131,49 @@ class ProfileScreenState extends State { @override Widget build(BuildContext context) { - privateKeyInput.text = Keys.nsecKey; - publicKeyInput.text = Keys.npubKey; + privateKeyInput.text = _toHex ? Keys.nsecKey : Keys.privateKey; + publicKeyInput.text = _toHex ? Keys.npubKey : Keys.publicKey; return ListView( children: [ - SizedBox( + const SizedBox( height: 60, ), - UserInfo(), - SizedBox( + const UserInfo(), + const SizedBox( height: 40, ), FormKeys(), - SizedBox(height: 20), + const SizedBox(height: 20), Padding( padding: const EdgeInsets.all(16.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Keys.keysExist - ? ElevatedButton( - style: ButtonStyle( - backgroundColor: - MaterialStateProperty.all(AppColors.background)), + ? IconButton( onPressed: () { - keysExistDialog( - Nostr.instance.keysService - .encodePublicKeyToNpub(Keys.publicKey), - Nostr.instance.keysService - .encodePrivateKeyToNsec(Keys.privateKey), - ); + setState(() { + _toHex = !_toHex; + }); }, - child: Text( - 'Keys', - ), - ) + icon: const Icon(Icons.refresh)) + // ElevatedButton( + // style: ButtonStyle( + // backgroundColor: + // MaterialStateProperty.all(AppColors.background)), + // onPressed: () { + // keysExistDialog( + // Nostr.instance.keysService + // .encodePublicKeyToNpub(Keys.publicKey), + // Nostr.instance.keysService + // .encodePrivateKeyToNsec(Keys.privateKey), + // ); + // }, + // child: const Text( + // 'Keys', + // ), + // ) : ElevatedButton( style: ButtonStyle( backgroundColor: @@ -171,7 +181,7 @@ class ProfileScreenState extends State { onPressed: () { modalBottomSheet(); }, - child: Text( + child: const Text( 'Generate Keys', ), ), diff --git a/lib/pages/profile_screen/profile_screen_widgets/delete_keys_dialog.dart b/lib/pages/profile_screen/profile_screen_widgets/delete_keys_dialog.dart deleted file mode 100644 index 8e4874f..0000000 --- a/lib/pages/profile_screen/profile_screen_widgets/delete_keys_dialog.dart +++ /dev/null @@ -1,87 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:drifter/theme/app_colors.dart'; - -import 'ok_button_widget.dart'; - -class DeleteKeysDialog extends StatelessWidget { - const DeleteKeysDialog({ - super.key, - required this.onNoPressed, - required this.onYesPressed, - }); - - final void Function()? onNoPressed; - final void Function()? onYesPressed; - - @override - Widget build(BuildContext context) { - return Dialog( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - child: Container( - constraints: const BoxConstraints(maxWidth: 600), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - color: Colors.white, - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - padding: const EdgeInsets.symmetric(vertical: 24), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - color: Colors.redAccent, - ), - child: const Center( - child: Text( - 'Delete Keys!', - style: TextStyle( - fontSize: 28, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - ), - ), - const SizedBox(height: 24), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Do you want to delete your keys?', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Colors.grey[700], - ), - ), - const SizedBox(height: 16), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: onNoPressed, - child: Text( - 'On', - style: TextStyle(color: AppColors.mainDarkBlue), - ), - ), - OkButton( - onPressed: onYesPressed, - label: 'YES', - ), - ], - ), - ], - ), - ) - ], - ), - ), - ); - } -} diff --git a/lib/pages/profile_screen/profile_screen_widgets/generated_keys.dart b/lib/pages/profile_screen/profile_screen_widgets/generated_keys.dart deleted file mode 100644 index 4049374..0000000 --- a/lib/pages/profile_screen/profile_screen_widgets/generated_keys.dart +++ /dev/null @@ -1,128 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'ok_button_widget.dart'; - -class GeneratedKeys extends StatefulWidget { - const GeneratedKeys({ - super.key, - required this.npubEncoded, - required this.nsecEncoded, - required this.hexPriv, - required this.hexPub, - }); - - final String npubEncoded; - final String nsecEncoded; - final String hexPriv; - final String hexPub; - - @override - State createState() => _GeneratedKeysState(); -} - -class _GeneratedKeysState extends State { - bool _toHex = false; - - @override - Widget build(BuildContext context) { - return Dialog( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - child: Container( - constraints: const BoxConstraints(maxWidth: 600), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - color: Colors.white, - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - padding: const EdgeInsets.symmetric(vertical: 24), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - color: Colors.indigo, - ), - child: const Center( - child: Text( - 'Keys', - style: TextStyle( - fontSize: 28, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - ), - ), - const SizedBox(height: 24), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Public Key', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Colors.grey[700], - ), - ), - const SizedBox(height: 12), - SelectableText( - _toHex ? widget.hexPub : widget.npubEncoded, - style: TextStyle( - fontSize: 16, - color: Colors.grey[800], - ), - ), - const SizedBox(height: 24), - Text( - 'Private Key', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Colors.grey[700], - ), - ), - const SizedBox(height: 12), - SelectableText( - _toHex ? widget.hexPriv : widget.nsecEncoded, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: Colors.redAccent, - ), - ), - const SizedBox(height: 24), - Row( - mainAxisAlignment: MainAxisAlignment - .spaceBetween, // Changed to space between to create space for icon buttons - children: [ - IconButton( - onPressed: () { - setState(() { - _toHex = !_toHex; - }); - }, - icon: const Icon(Icons.autorenew_outlined), - color: Colors.grey[700], - ), - OkButton( - onPressed: () { - Navigator.pop(context); - }, - label: 'OK', - ), - ], - ) - ], - ), - ), - ], - ), - ), - ); - } -} diff --git a/lib/pages/profile_screen/profile_screen_widgets/key_exist_dialog.dart b/lib/pages/profile_screen/profile_screen_widgets/key_exist_dialog.dart deleted file mode 100644 index d74e34f..0000000 --- a/lib/pages/profile_screen/profile_screen_widgets/key_exist_dialog.dart +++ /dev/null @@ -1,128 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:drifter/theme/app_colors.dart'; - -import 'ok_button_widget.dart'; - -class KeysExistDialog extends StatefulWidget { - const KeysExistDialog({ - super.key, - required this.npubEncoded, - required this.nsecEncoded, - required this.hexPriv, - required this.hexPub, - }); - - final String npubEncoded; - final String nsecEncoded; - final String hexPriv; - final String hexPub; - - @override - State createState() => _KeysExistDialogState(); -} - -class _KeysExistDialogState extends State { - bool _toHex = false; - - @override - Widget build(BuildContext context) { - return Dialog( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - child: Container( - constraints: const BoxConstraints(maxWidth: 600), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - color: Colors.white, - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - padding: const EdgeInsets.symmetric(vertical: 24), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - color: AppColors.mainDarkBlue, - ), - child: const Center( - child: Text( - 'Keys', - style: TextStyle( - fontSize: 28, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - ), - ), - const SizedBox(height: 24), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Public Key', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Colors.grey[700], - ), - ), - const SizedBox(height: 12), - SelectableText( - _toHex ? widget.hexPub : widget.npubEncoded, - style: TextStyle( - fontSize: 16, - color: Colors.grey[800], - ), - ), - const SizedBox(height: 24), - Text( - 'Private Key', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Colors.grey[700], - ), - ), - const SizedBox(height: 12), - SelectableText( - _toHex ? widget.hexPriv : widget.nsecEncoded, - style: TextStyle( - fontSize: 16, - color: Colors.grey[800], - ), - ), - const SizedBox(height: 24), - Row( - mainAxisAlignment: MainAxisAlignment - .spaceBetween, // Changed to space between to create space for icon buttons - children: [ - IconButton( - onPressed: () { - setState(() { - _toHex = !_toHex; - }); - }, - icon: const Icon(Icons.autorenew_outlined), - color: Colors.grey[700], - ), - OkButton( - onPressed: () { - Navigator.pop(context); - }, - label: 'OK', - ), - ], - ) - ], - ), - ), - ], - ), - ), - ); - } -} diff --git a/lib/pages/profile_screen/profile_screen_widgets/keys_option_modal_bottom_sheet.dart b/lib/pages/profile_screen/profile_screen_widgets/keys_option_modal_bottom_sheet.dart deleted file mode 100644 index 25ad2e5..0000000 --- a/lib/pages/profile_screen/profile_screen_widgets/keys_option_modal_bottom_sheet.dart +++ /dev/null @@ -1,34 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:drifter/theme/app_colors.dart'; - -class KeysOptionModalBottomSheet extends StatelessWidget { - const KeysOptionModalBottomSheet({ - super.key, - required this.generateNewKeyPressed, - }); - - final void Function()? generateNewKeyPressed; - - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.all(20), - decoration: BoxDecoration(color: AppColors.mainDarkBlue), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - ElevatedButton( - style: ButtonStyle( - backgroundColor: MaterialStateProperty.all(Colors.white)), - onPressed: generateNewKeyPressed, - child: Text( - 'Generate New Key', - style: TextStyle(color: AppColors.mainDarkBlue), - ), - ), - const SizedBox(height: 10), - ], - ), - ); - } -} diff --git a/lib/pages/profile_screen/profile_screen_widgets/message_snack_bar.dart b/lib/pages/profile_screen/profile_screen_widgets/message_snack_bar.dart deleted file mode 100644 index d5c4fd1..0000000 --- a/lib/pages/profile_screen/profile_screen_widgets/message_snack_bar.dart +++ /dev/null @@ -1,46 +0,0 @@ -import 'package:flutter/material.dart'; - -class MessageSnackBar extends SnackBar { - MessageSnackBar({Key? key, required this.label, this.isWarning = false}) - : super( - key: key, - content: _GenericErrorSnackBarMessage( - label: label, - isWarning: isWarning, - ), - backgroundColor: isWarning! ? Colors.red : Colors.white, - elevation: 6.0, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10.0), - ), - behavior: SnackBarBehavior.fixed, - ); - - final String label; - final bool? isWarning; -} - -class _GenericErrorSnackBarMessage extends StatelessWidget { - const _GenericErrorSnackBarMessage({ - Key? key, - required this.label, - this.isWarning, - }) : super(key: key); - - final String label; - final bool? isWarning; - - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 24.0), - child: Text( - label, - style: TextStyle( - color: isWarning! ? Colors.white : Colors.black, - fontSize: 16.0, - ), - ), - ); - } -} diff --git a/lib/pages/profile_screen/profile_screen_widgets/ok_button_widget.dart b/lib/pages/profile_screen/profile_screen_widgets/ok_button_widget.dart deleted file mode 100644 index 6dbaad7..0000000 --- a/lib/pages/profile_screen/profile_screen_widgets/ok_button_widget.dart +++ /dev/null @@ -1,34 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:drifter/theme/app_colors.dart'; - -class OkButton extends StatelessWidget { - const OkButton({ - super.key, - required this.onPressed, - required this.label, - }); - - final void Function()? onPressed; - final String label; - - @override - Widget build(BuildContext context) { - return ElevatedButton( - onPressed: onPressed, - style: ElevatedButton.styleFrom( - backgroundColor: AppColors.mainDarkBlue, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - child: Text( - label, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - ); - } -} diff --git a/lib/pages/profile_screen/profile_screen_widgets/user_info_widget.dart b/lib/pages/profile_screen/profile_screen_widgets/user_info_widget.dart deleted file mode 100644 index 53c47f4..0000000 --- a/lib/pages/profile_screen/profile_screen_widgets/user_info_widget.dart +++ /dev/null @@ -1,97 +0,0 @@ -import 'package:drifter/theme/app_colors.dart'; -import 'package:flutter/material.dart'; - -class UserInfo extends StatelessWidget { - const UserInfo({super.key}); - - @override - Widget build(BuildContext context) { - return Container( - child: Column( - children: [ - AvatarWidget(), - SizedBox( - height: 10, - ), - UserNameWidget(), - ], - ), - ); - } -} - -class AvatarWidget extends StatelessWidget { - const AvatarWidget({super.key}); - - @override - Widget build(BuildContext context) { - return Container( - decoration: BoxDecoration( - border: Border.all(color: Colors.black), - borderRadius: BorderRadius.all(Radius.circular(75))), - width: 150, - height: 150, - ); - } -} - -class UserNameWidget extends StatefulWidget { - const UserNameWidget({super.key}); - - @override - State createState() => _UserNameWidgetState(); -} - -class _UserNameWidgetState extends State { - late final TextEditingController messageController; - late final FocusNode messageFocusNode; - - @override - void initState() { - messageController = TextEditingController(); - messageFocusNode = FocusNode(); - - super.initState(); - } - - @override - void dispose() { - messageController.dispose(); - messageFocusNode.dispose(); - - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.all(4.0), - child: ClipRRect( - borderRadius: const BorderRadius.all( - Radius.circular( - 0.0, - ), - ), - child: TextField( - controller: messageController, - focusNode: messageFocusNode, - style: const TextStyle( - fontSize: 14, - ), - decoration: InputDecoration( - hintText: 'Username', - hintStyle: const TextStyle(fontSize: 14), - suffixIcon: IconButton( - icon: const Icon( - Icons.send, - color: AppColors.mainDarkBlue, - size: 30, - ), - onPressed: () {}, - ), - ), - ), - ), - ); - } -}