@@ -9,6 +9,8 @@ class NetworkFormResult {
99 required this .nickname,
1010 required this .altNickname,
1111 required this .useTls,
12+ this .webSocketPort,
13+ this .webSocketPath,
1214 required this .autoConnect,
1315 required this .saslMechanism,
1416 this .saslAccount,
@@ -21,6 +23,8 @@ class NetworkFormResult {
2123 final String nickname;
2224 final String altNickname;
2325 final bool useTls;
26+ final int ? webSocketPort;
27+ final String ? webSocketPath;
2428 final bool autoConnect;
2529 final SaslMechanism saslMechanism;
2630 final String ? saslAccount;
@@ -44,6 +48,8 @@ class _NetworkFormScreenState extends State<NetworkFormScreen> {
4448 late final TextEditingController _nameController;
4549 late final TextEditingController _hostController;
4650 late final TextEditingController _portController;
51+ late final TextEditingController _webSocketPortController;
52+ late final TextEditingController _webSocketPathController;
4753 late final TextEditingController _nicknameController;
4854 late final TextEditingController _altNicknameController;
4955 late final TextEditingController _saslAccountController;
@@ -61,6 +67,12 @@ class _NetworkFormScreenState extends State<NetworkFormScreen> {
6167 _portController = TextEditingController (
6268 text: (initial? .port ?? 6697 ).toString (),
6369 );
70+ _webSocketPortController = TextEditingController (
71+ text: initial? .webSocketPort? .toString () ?? '' ,
72+ );
73+ _webSocketPathController = TextEditingController (
74+ text: initial? .webSocketPath ?? '' ,
75+ );
6476 _nicknameController = TextEditingController (
6577 text: initial? .nickname ?? 'AndroidIRCX' ,
6678 );
@@ -79,6 +91,8 @@ class _NetworkFormScreenState extends State<NetworkFormScreen> {
7991 _nameController.dispose ();
8092 _hostController.dispose ();
8193 _portController.dispose ();
94+ _webSocketPortController.dispose ();
95+ _webSocketPathController.dispose ();
8296 _nicknameController.dispose ();
8397 _altNicknameController.dispose ();
8498 _saslAccountController.dispose ();
@@ -128,6 +142,42 @@ class _NetworkFormScreenState extends State<NetworkFormScreen> {
128142 },
129143 ),
130144 const SizedBox (height: 16 ),
145+ TextFormField (
146+ controller: _webSocketPortController,
147+ keyboardType: TextInputType .number,
148+ decoration: const InputDecoration (
149+ labelText: 'WebSocket port' ,
150+ helperText: 'Optional. Used by Flutter Web instead of raw IRC port.' ,
151+ ),
152+ validator: (value) {
153+ if ((value ?? '' ).trim ().isEmpty) {
154+ return null ;
155+ }
156+ if (int .tryParse (value! .trim ()) == null ) {
157+ return 'Enter a valid WebSocket port.' ;
158+ }
159+ return null ;
160+ },
161+ ),
162+ const SizedBox (height: 16 ),
163+ TextFormField (
164+ controller: _webSocketPathController,
165+ decoration: const InputDecoration (
166+ labelText: 'WebSocket path' ,
167+ helperText: 'Optional. Example: /irc or /websocket. Leave empty for root path.' ,
168+ ),
169+ validator: (value) {
170+ final trimmed = (value ?? '' ).trim ();
171+ if (trimmed.isEmpty) {
172+ return null ;
173+ }
174+ if (! trimmed.startsWith ('/' )) {
175+ return 'WebSocket path must start with /.' ;
176+ }
177+ return null ;
178+ },
179+ ),
180+ const SizedBox (height: 16 ),
131181 TextFormField (
132182 controller: _nicknameController,
133183 decoration: const InputDecoration (labelText: 'Nickname' ),
@@ -239,6 +289,10 @@ class _NetworkFormScreenState extends State<NetworkFormScreen> {
239289 nickname: _nicknameController.text.trim (),
240290 altNickname: _altNicknameController.text.trim (),
241291 useTls: _useTls,
292+ webSocketPort: (_webSocketPortController.text.trim ().isEmpty)
293+ ? null
294+ : int .parse (_webSocketPortController.text.trim ()),
295+ webSocketPath: _webSocketPathController.text.trim (),
242296 autoConnect: _autoConnect,
243297 saslMechanism: _saslMechanism,
244298 saslAccount: _saslAccountController.text.trim (),
0 commit comments