11import 'package:flutter/material.dart' ;
2+ import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart' ;
23import 'package:threebotlogin/widgets/council/councils.dart' ;
34import 'package:threebotlogin/widgets/layout_drawer.dart' ;
45import 'package:validators/validators.dart' ;
@@ -18,117 +19,128 @@ class _CouncilScreenState extends State<CouncilScreen> {
1819 Widget build (BuildContext context) {
1920 const size = 100.0 ;
2021 final content = Padding (
21- padding: const EdgeInsets .all (16.0 ),
22- child: Column (
23- mainAxisAlignment: MainAxisAlignment .center,
24- children: [
25- TextField (
26- style: Theme .of (context).textTheme.bodyLarge! .copyWith (
27- color: Theme .of (context).colorScheme.onSurface,
28- ),
29- controller: urlController,
30- onChanged: (value) {
31- final v = value.trim ();
32- if (v.isEmpty) {
33- errorMessage = 'URL is required' ;
34- setState (() {});
35- return ;
36- }
37- if (! v.startsWith ('wss://' ) && ! v.startsWith ('ws://' )) {
38- errorMessage = 'Not a valid websocket URL' ;
39- setState (() {});
40- return ;
41- }
42- if (! isFQDN (v.replaceFirst ('wss://' , '' )) &&
43- ! isFQDN (v.replaceFirst ('ws://' , '' ))) {
44- errorMessage = 'Not a valid websocket URL' ;
45- setState (() {});
46- return ;
47- }
48- errorMessage = null ;
49- setState (() {});
50- return ;
51- },
52- decoration: InputDecoration (
53- labelText: 'TFChain URL' ,
54- errorText: errorMessage,
55- )),
56- const SizedBox (height: 50 ),
57- Row (
58- mainAxisAlignment: MainAxisAlignment .spaceEvenly,
59- children: [
60- ElevatedButton (
61- style: ElevatedButton .styleFrom (
62- fixedSize: const Size .fromWidth (size)),
63- onPressed: () {
64- urlController.text = 'wss://tfchain.dev.grid.tf' ;
65- errorMessage = null ;
66- setState (() {});
67- },
68- child: const Text ('Devnet' )),
69- ElevatedButton (
70- style: ElevatedButton .styleFrom (
71- fixedSize: const Size .fromWidth (size)),
72- onPressed: () {
73- urlController.text = 'wss://tfchain.qa.grid.tf' ;
74- errorMessage = null ;
75- setState (() {});
76- },
77- child: const Text ('QAnet' )),
78- ],
79- ),
80- const SizedBox (height: 20 ),
81- Row (
82- mainAxisAlignment: MainAxisAlignment .spaceEvenly,
83- children: [
84- ElevatedButton (
85- style: ElevatedButton .styleFrom (
86- fixedSize: const Size .fromWidth (size)),
87- onPressed: () {
88- urlController.text = 'wss://tfchain.test.grid.tf' ;
89- errorMessage = null ;
90- setState (() {});
91- },
92- child: const Text ('Testnet' )),
93- ElevatedButton (
94- style: ElevatedButton .styleFrom (
95- fixedSize: const Size .fromWidth (size)),
96- onPressed: () {
97- urlController.text = 'wss://tfchain.grid.tf' ;
98- errorMessage = null ;
99- setState (() {});
100- },
101- child: const Text ('Mainnet' )),
102- ],
103- ),
104- const SizedBox (height: 50 ),
105- ElevatedButton (
106- onPressed: () {
107- if (errorMessage == null ) {
108- Navigator .of (context).push (MaterialPageRoute (
109- builder: (context) =>
110- CouncilsWidget (chainUrl: urlController.text),
111- ));
112- }
22+ padding: const EdgeInsets .all (16.0 ),
23+ child: KeyboardVisibilityBuilder (builder: (context, isKeyboardVisible) {
24+ return GestureDetector (
25+ behavior: HitTestBehavior .opaque,
26+ onTap: () {
27+ FocusScope .of (context).unfocus ();
11328 },
114- style: ElevatedButton .styleFrom (
115- backgroundColor: errorMessage == null
116- ? Theme .of (context).colorScheme.primaryContainer
117- : Theme .of (context).colorScheme.surfaceContainerHighest),
118- child: SizedBox (
119- width: double .infinity,
120- child: Text (
121- style: Theme .of (context).textTheme.titleLarge! .copyWith (
122- color: errorMessage == null
123- ? Theme .of (context).colorScheme.primary
124- : Colors .grey,
125- fontWeight: FontWeight .bold),
126- 'Connect' ,
127- textAlign: TextAlign .center,
128- )))
129- ],
130- ),
131- );
29+ child: Column (
30+ mainAxisAlignment: MainAxisAlignment .center,
31+ children: [
32+ TextField (
33+ style: Theme .of (context).textTheme.bodyLarge! .copyWith (
34+ color: Theme .of (context).colorScheme.onSurface,
35+ ),
36+ controller: urlController,
37+ onChanged: (value) {
38+ final v = value.trim ();
39+ if (v.isEmpty) {
40+ errorMessage = 'URL is required' ;
41+ setState (() {});
42+ return ;
43+ }
44+ if (! v.startsWith ('wss://' ) && ! v.startsWith ('ws://' )) {
45+ errorMessage = 'Not a valid websocket URL' ;
46+ setState (() {});
47+ return ;
48+ }
49+ if (! isFQDN (v.replaceFirst ('wss://' , '' )) &&
50+ ! isFQDN (v.replaceFirst ('ws://' , '' ))) {
51+ errorMessage = 'Not a valid websocket URL' ;
52+ setState (() {});
53+ return ;
54+ }
55+ errorMessage = null ;
56+ setState (() {});
57+ return ;
58+ },
59+ decoration: InputDecoration (
60+ labelText: 'TFChain URL' ,
61+ errorText: errorMessage,
62+ )),
63+ const SizedBox (height: 50 ),
64+ Row (
65+ mainAxisAlignment: MainAxisAlignment .spaceEvenly,
66+ children: [
67+ ElevatedButton (
68+ style: ElevatedButton .styleFrom (
69+ fixedSize: const Size .fromWidth (size)),
70+ onPressed: () {
71+ urlController.text = 'wss://tfchain.dev.grid.tf' ;
72+ errorMessage = null ;
73+ setState (() {});
74+ },
75+ child: const Text ('Devnet' )),
76+ ElevatedButton (
77+ style: ElevatedButton .styleFrom (
78+ fixedSize: const Size .fromWidth (size)),
79+ onPressed: () {
80+ urlController.text = 'wss://tfchain.qa.grid.tf' ;
81+ errorMessage = null ;
82+ setState (() {});
83+ },
84+ child: const Text ('QAnet' )),
85+ ],
86+ ),
87+ const SizedBox (height: 20 ),
88+ Row (
89+ mainAxisAlignment: MainAxisAlignment .spaceEvenly,
90+ children: [
91+ ElevatedButton (
92+ style: ElevatedButton .styleFrom (
93+ fixedSize: const Size .fromWidth (size)),
94+ onPressed: () {
95+ urlController.text = 'wss://tfchain.test.grid.tf' ;
96+ errorMessage = null ;
97+ setState (() {});
98+ },
99+ child: const Text ('Testnet' )),
100+ ElevatedButton (
101+ style: ElevatedButton .styleFrom (
102+ fixedSize: const Size .fromWidth (size)),
103+ onPressed: () {
104+ urlController.text = 'wss://tfchain.grid.tf' ;
105+ errorMessage = null ;
106+ setState (() {});
107+ },
108+ child: const Text ('Mainnet' )),
109+ ],
110+ ),
111+ const SizedBox (height: 50 ),
112+ ElevatedButton (
113+ onPressed: () {
114+ if (errorMessage == null ) {
115+ Navigator .of (context).push (MaterialPageRoute (
116+ builder: (context) =>
117+ CouncilsWidget (chainUrl: urlController.text),
118+ ));
119+ }
120+ },
121+ style: ElevatedButton .styleFrom (
122+ backgroundColor: errorMessage == null
123+ ? Theme .of (context).colorScheme.primaryContainer
124+ : Theme .of (context)
125+ .colorScheme
126+ .surfaceContainerHighest),
127+ child: SizedBox (
128+ width: double .infinity,
129+ child: Text (
130+ style: Theme .of (context)
131+ .textTheme
132+ .titleLarge!
133+ .copyWith (
134+ color: errorMessage == null
135+ ? Theme .of (context).colorScheme.primary
136+ : Colors .grey,
137+ fontWeight: FontWeight .bold),
138+ 'Connect' ,
139+ textAlign: TextAlign .center,
140+ )))
141+ ],
142+ ));
143+ }));
132144 return LayoutDrawer (titleText: 'Council' , content: content);
133145 }
134146}
0 commit comments