fixed rendering bug on linux + ip configuration
This commit is contained in:
@ -279,7 +279,7 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'Port: ${project.port} • ${project.packages.length} package(s)',
|
||||
'${project.ipAddress}:${project.port} • ${project.packages.length} package(s)',
|
||||
style:
|
||||
Theme.of(context).textTheme.bodySmall,
|
||||
),
|
||||
|
||||
@ -20,17 +20,20 @@ class _ProjectScreenState extends State<ProjectScreen> {
|
||||
final UdpService _udpService = UdpService();
|
||||
String? _lastSentPackageId;
|
||||
bool _isSending = false;
|
||||
late TextEditingController _ipController;
|
||||
late TextEditingController _portController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_project = widget.project;
|
||||
_ipController = TextEditingController(text: _project.ipAddress);
|
||||
_portController = TextEditingController(text: _project.port.toString());
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_ipController.dispose();
|
||||
_portController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
@ -75,17 +78,58 @@ class _ProjectScreenState extends State<ProjectScreen> {
|
||||
);
|
||||
}
|
||||
|
||||
void _updatePort() {
|
||||
void _updateSettings() {
|
||||
final ip = _ipController.text.trim();
|
||||
final port = int.tryParse(_portController.text);
|
||||
if (port != null && port >= 1 && port <= 65535) {
|
||||
|
||||
// Validate IP address
|
||||
final ipPattern = RegExp(r'^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$');
|
||||
bool isValidIp = ipPattern.hasMatch(ip);
|
||||
if (isValidIp) {
|
||||
final parts = ip.split('.');
|
||||
for (final part in parts) {
|
||||
final num = int.tryParse(part);
|
||||
if (num == null || num < 0 || num > 255) {
|
||||
isValidIp = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validate port
|
||||
final isValidPort = port != null && port >= 1 && port <= 65535;
|
||||
|
||||
if (isValidIp && isValidPort) {
|
||||
setState(() {
|
||||
_project = _project.copyWith(port: port);
|
||||
_project = _project.copyWith(
|
||||
ipAddress: ip,
|
||||
port: port,
|
||||
);
|
||||
});
|
||||
} else {
|
||||
_portController.text = _project.port.toString();
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Invalid port number (1-65535)'),
|
||||
content: Text('Settings updated successfully!'),
|
||||
backgroundColor: Colors.green,
|
||||
behavior: SnackBarBehavior.floating,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
// Revert to current project values
|
||||
_ipController.text = _project.ipAddress;
|
||||
_portController.text = _project.port.toString();
|
||||
|
||||
String errorMessage = 'Invalid ';
|
||||
if (!isValidIp && !isValidPort) {
|
||||
errorMessage += 'IP address and port number';
|
||||
} else if (!isValidIp) {
|
||||
errorMessage += 'IP address';
|
||||
} else {
|
||||
errorMessage += 'port number (1-65535)';
|
||||
}
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(errorMessage),
|
||||
backgroundColor: Colors.red,
|
||||
behavior: SnackBarBehavior.floating,
|
||||
),
|
||||
@ -128,7 +172,7 @@ class _ProjectScreenState extends State<ProjectScreen> {
|
||||
|
||||
final success = await _udpService.sendPackage(
|
||||
data: package.data,
|
||||
ipAddress: package.ipAddress,
|
||||
ipAddress: _project.ipAddress, // Use project IP to override package IP
|
||||
port: _project.port,
|
||||
);
|
||||
|
||||
@ -212,6 +256,18 @@ class _ProjectScreenState extends State<ProjectScreen> {
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
controller: _ipController,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'IP Address',
|
||||
prefixIcon: Icon(Icons.computer),
|
||||
isDense: true,
|
||||
),
|
||||
onSubmitted: (_) => _updateSettings(),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: TextField(
|
||||
controller: _portController,
|
||||
@ -224,12 +280,12 @@ class _ProjectScreenState extends State<ProjectScreen> {
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly
|
||||
],
|
||||
onSubmitted: (_) => _updatePort(),
|
||||
onSubmitted: (_) => _updateSettings(),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
FilledButton.icon(
|
||||
onPressed: _updatePort,
|
||||
onPressed: _updateSettings,
|
||||
icon: const Icon(Icons.check, size: 18),
|
||||
label: const Text('Apply'),
|
||||
),
|
||||
@ -265,15 +321,26 @@ class _ProjectScreenState extends State<ProjectScreen> {
|
||||
],
|
||||
),
|
||||
)
|
||||
: ListView.builder(
|
||||
padding: const EdgeInsets.all(16),
|
||||
itemCount: _project.packages.length,
|
||||
itemBuilder: (context, index) {
|
||||
final package = _project.packages[index];
|
||||
final wasSent = _lastSentPackageId == package.id;
|
||||
: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
// Use 2 columns when width is >= 800px, otherwise 1 column
|
||||
final crossAxisCount = constraints.maxWidth >= 800 ? 2 : 1;
|
||||
final aspectRatio = constraints.maxWidth >= 800 ? 2.5 : 2.0;
|
||||
|
||||
return GridView.builder(
|
||||
padding: const EdgeInsets.all(16),
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: crossAxisCount,
|
||||
childAspectRatio: aspectRatio,
|
||||
crossAxisSpacing: 12,
|
||||
mainAxisSpacing: 12,
|
||||
),
|
||||
itemCount: _project.packages.length,
|
||||
itemBuilder: (context, index) {
|
||||
final package = _project.packages[index];
|
||||
final wasSent = _lastSentPackageId == package.id;
|
||||
|
||||
return Card(
|
||||
margin: const EdgeInsets.only(bottom: 12),
|
||||
return Card(
|
||||
color: wasSent
|
||||
? Theme.of(context).colorScheme.primaryContainer
|
||||
: null,
|
||||
@ -335,7 +402,7 @@ class _ProjectScreenState extends State<ProjectScreen> {
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'To: ${package.ipAddress}',
|
||||
'To: ${_project.ipAddress}:${_project.port}',
|
||||
style:
|
||||
Theme.of(context).textTheme.bodySmall,
|
||||
),
|
||||
@ -455,6 +522,8 @@ class _ProjectScreenState extends State<ProjectScreen> {
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user