| .. | .. |
|---|
| 158 | 158 | hintText: '192.168.1.100', |
|---|
| 159 | 159 | ), |
|---|
| 160 | 160 | keyboardType: TextInputType.url, |
|---|
| 161 | + validator: (v) { |
|---|
| 162 | + if (v == null || v.trim().isEmpty) return null; |
|---|
| 163 | + final ip = RegExp(r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$'); |
|---|
| 164 | + return ip.hasMatch(v.trim()) ? null : 'Enter a valid IP address'; |
|---|
| 165 | + }, |
|---|
| 161 | 166 | ), |
|---|
| 162 | 167 | const SizedBox(height: 16), |
|---|
| 163 | 168 | |
|---|
| .. | .. |
|---|
| 171 | 176 | hintText: '10.8.0.1 (OpenVPN static IP)', |
|---|
| 172 | 177 | ), |
|---|
| 173 | 178 | keyboardType: TextInputType.url, |
|---|
| 179 | + validator: (v) { |
|---|
| 180 | + if (v == null || v.trim().isEmpty) return null; |
|---|
| 181 | + final ip = RegExp(r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$'); |
|---|
| 182 | + return ip.hasMatch(v.trim()) ? null : 'Enter a valid IP address'; |
|---|
| 183 | + }, |
|---|
| 174 | 184 | ), |
|---|
| 175 | 185 | const SizedBox(height: 16), |
|---|
| 176 | 186 | |
|---|
| .. | .. |
|---|
| 198 | 208 | hintText: '8765', |
|---|
| 199 | 209 | ), |
|---|
| 200 | 210 | keyboardType: TextInputType.number, |
|---|
| 211 | + validator: (v) { |
|---|
| 212 | + if (v == null || v.trim().isEmpty) return 'Required'; |
|---|
| 213 | + final port = int.tryParse(v.trim()); |
|---|
| 214 | + if (port == null || port < 1 || port > 65535) { |
|---|
| 215 | + return 'Port must be 1–65535'; |
|---|
| 216 | + } |
|---|
| 217 | + return null; |
|---|
| 218 | + }, |
|---|
| 201 | 219 | ), |
|---|
| 202 | 220 | const SizedBox(height: 16), |
|---|
| 203 | 221 | |
|---|
| .. | .. |
|---|
| 210 | 228 | decoration: const InputDecoration( |
|---|
| 211 | 229 | hintText: 'AA:BB:CC:DD:EE:FF', |
|---|
| 212 | 230 | ), |
|---|
| 231 | + validator: (v) { |
|---|
| 232 | + if (v == null || v.trim().isEmpty) return null; |
|---|
| 233 | + final mac = RegExp( |
|---|
| 234 | + r'^[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}$'); |
|---|
| 235 | + return mac.hasMatch(v.trim()) |
|---|
| 236 | + ? null |
|---|
| 237 | + : 'Enter a valid MAC address (AA:BB:CC:DD:EE:FF)'; |
|---|
| 238 | + }, |
|---|
| 213 | 239 | ), |
|---|
| 214 | 240 | const SizedBox(height: 16), |
|---|
| 215 | 241 | |
|---|