Skip to content

Commit 9b74a21

Browse files
committed
fix:支持编辑连接名称,修新增连接的逻辑问题
1 parent 5a3d5ac commit 9b74a21

File tree

3 files changed

+152
-49
lines changed

3 files changed

+152
-49
lines changed

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
# connecter
22
A lightweight SSH connection tool based on flutter
33
# todo
4-
* 连接名称的编辑
54
* SFTP
65
* 极端情况下的overflow
76
# harmonyos端迁移
8-
* 初步完成,但疑似ohos和其他端无法兼容,待上述问题解决后在新的分支修复
7+
* 初步完成,但疑似ohos和其他端的源代码无法兼容,待上述问题解决后在新的分支修复
98
* 问题:
109
1. 任何情况下的overflow
1110
2. 无法读取/保存任何数据

lib/manage_connections_page.dart

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ import 'models/connection_model.dart';
66
import 'services/storage_service.dart';
77
import 'quick_connect_dialog.dart';
88
import 'services/ssh_service.dart';
9-
//import 'services/storage_service.dart';
9+
1010

1111
class ManageConnectionsPage extends StatefulWidget {
1212
const ManageConnectionsPage({super.key});
1313

1414
@override
1515
State<ManageConnectionsPage> createState() => _ManageConnectionsPageState();
16-
}
16+
}
1717

1818
class _ManageConnectionsPageState extends State<ManageConnectionsPage> {
1919
final _storageService = StorageService();
@@ -32,10 +32,11 @@ class _ManageConnectionsPageState extends State<ManageConnectionsPage> {
3232
});
3333
}
3434

35+
3536
void _editConnection(ConnectionInfo connection) {
3637
showDialog(
3738
context: context,
38-
builder: (context) => QuickConnectDialog(connection: connection),
39+
builder: (context) => QuickConnectDialog(connection: connection),
3940
).then((_) => _loadConnections());
4041
}
4142

@@ -73,20 +74,12 @@ void _connectTo(ConnectionInfo connection) async {
7374
final storageService = StorageService();
7475
final sshService = SshService();
7576

76-
// 获取对应的凭证
7777
final credentials = await storageService.getCredentials();
7878
final credential = credentials.firstWhere(
7979
(c) => c.id == connection.credentialId,
8080
orElse: () => throw Exception('找不到认证凭证'),
8181
);
8282

83-
// 显示连接中状态
84-
if (mounted) {
85-
ScaffoldMessenger.of(context).showSnackBar(
86-
const SnackBar(content: Text('正在连接...')),
87-
);
88-
}
89-
9083
await sshService.connect(connection, credential);
9184

9285
if (mounted) {
@@ -118,6 +111,12 @@ void _connectTo(ConnectionInfo connection) async {
118111
}
119112
}
120113
}
114+
void _showNewConnectionDialog() {
115+
showDialog(
116+
context: context,
117+
builder: (context) => const QuickConnectDialog(isNewConnection: true),
118+
).then((_) => _loadConnections());
119+
}
121120

122121
@override
123122
Widget build(BuildContext context) {
@@ -126,12 +125,7 @@ void _connectTo(ConnectionInfo connection) async {
126125
title: const Text('管理连接'),
127126
actions: [
128127
IconButton(
129-
onPressed: () {
130-
showDialog(
131-
context: context,
132-
builder: (context) => const QuickConnectDialog(),
133-
).then((_) => _loadConnections());
134-
},
128+
onPressed: _showNewConnectionDialog,
135129
icon: const Icon(Icons.add),
136130
),
137131
],

lib/quick_connect_dialog.dart

Lines changed: 140 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,23 @@ import 'services/storage_service.dart';
77
import 'services/ssh_service.dart';
88
import 'terminal_page.dart';
99

10-
1110
class QuickConnectDialog extends StatefulWidget {
12-
final ConnectionInfo? connection;
11+
final ConnectionInfo? connection;
12+
final bool isNewConnection; // 新增:标识是否为新建连接
1313

14-
const QuickConnectDialog({super.key, this.connection});
14+
const QuickConnectDialog({
15+
super.key,
16+
this.connection,
17+
this.isNewConnection = false, // 默认为false
18+
});
1519

1620
@override
1721
State<QuickConnectDialog> createState() => _QuickConnectDialogState();
1822
}
1923

2024
class _QuickConnectDialogState extends State<QuickConnectDialog> {
2125
final _formKey = GlobalKey<FormState>();
26+
final _nameController = TextEditingController();
2227
final _hostController = TextEditingController();
2328
final _portController = TextEditingController(text: '22');
2429
final _storageService = StorageService();
@@ -37,10 +42,15 @@ class _QuickConnectDialogState extends State<QuickConnectDialog> {
3742
_isEditing = widget.connection != null;
3843

3944
if (_isEditing) {
45+
// 编辑模式:预填充所有字段
46+
_nameController.text = widget.connection!.name;
4047
_hostController.text = widget.connection!.host;
4148
_portController.text = widget.connection!.port.toString();
4249
_selectedType = widget.connection!.type;
4350
_rememberConnection = widget.connection!.remember;
51+
} else {
52+
// 新建连接或快速连接模式:设置默认名称
53+
_nameController.text = '新连接';
4454
}
4555

4656
_loadCredentials();
@@ -61,6 +71,24 @@ class _QuickConnectDialogState extends State<QuickConnectDialog> {
6171
setState(() {
6272
_selectedCredential = credential;
6373
});
74+
} else if (_credentials.isNotEmpty) {
75+
// 新建连接或快速连接模式:默认选择第一个凭证
76+
setState(() {
77+
_selectedCredential = _credentials.first;
78+
});
79+
}
80+
}
81+
82+
// 自动生成连接名称
83+
void _generateConnectionName() {
84+
if (!_isEditing && (_hostController.text.isNotEmpty || _portController.text.isNotEmpty)) {
85+
final host = _hostController.text;
86+
final port = _portController.text;
87+
if (host.isNotEmpty) {
88+
setState(() {
89+
_nameController.text = '$host:$port';
90+
});
91+
}
6492
}
6593
}
6694

@@ -80,7 +108,7 @@ class _QuickConnectDialogState extends State<QuickConnectDialog> {
80108
try {
81109
final connection = ConnectionInfo(
82110
id: widget.connection?.id ?? const Uuid().v4(),
83-
name: '${_hostController.text}:${_portController.text}',
111+
name: _nameController.text,
84112
host: _hostController.text,
85113
port: int.parse(_portController.text),
86114
credentialId: _selectedCredential!.id,
@@ -118,7 +146,6 @@ class _QuickConnectDialogState extends State<QuickConnectDialog> {
118146
}
119147
}
120148

121-
// 新增:仅更新连接信息而不连接
122149
Future<void> _updateConnection() async {
123150
if (!_formKey.currentState!.validate()) return;
124151
if (_selectedCredential == null) {
@@ -134,21 +161,19 @@ class _QuickConnectDialogState extends State<QuickConnectDialog> {
134161

135162
try {
136163
final connection = ConnectionInfo(
137-
id: widget.connection!.id, // 使用原有的ID
138-
name: '${_hostController.text}:${_portController.text}',
164+
id: widget.connection!.id,
165+
name: _nameController.text,
139166
host: _hostController.text,
140167
port: int.parse(_portController.text),
141168
credentialId: _selectedCredential!.id,
142169
type: _selectedType,
143-
remember: true, // 编辑模式下总是记住连接
170+
remember: true,
144171
);
145172

146-
// 仅保存连接信息,不进行SSH连接
147173
await _storageService.saveConnection(connection);
148174

149175
if (mounted) {
150176
Navigator.of(context).pop();
151-
// 不跳转到终端页面
152177
ScaffoldMessenger.of(context).showSnackBar(
153178
const SnackBar(content: Text('连接信息已更新')),
154179
);
@@ -168,6 +193,54 @@ class _QuickConnectDialogState extends State<QuickConnectDialog> {
168193
}
169194
}
170195

196+
// 新增:仅保存连接而不连接
197+
Future<void> _saveConnectionOnly() async {
198+
if (!_formKey.currentState!.validate()) return;
199+
if (_selectedCredential == null) {
200+
ScaffoldMessenger.of(context).showSnackBar(
201+
const SnackBar(content: Text('请选择认证凭证')),
202+
);
203+
return;
204+
}
205+
206+
setState(() {
207+
_isConnecting = true;
208+
});
209+
210+
try {
211+
final connection = ConnectionInfo(
212+
id: const Uuid().v4(),
213+
name: _nameController.text,
214+
host: _hostController.text,
215+
port: int.parse(_portController.text),
216+
credentialId: _selectedCredential!.id,
217+
type: _selectedType,
218+
remember: true, // 新建连接总是保存
219+
);
220+
221+
await _storageService.saveConnection(connection);
222+
223+
if (mounted) {
224+
Navigator.of(context).pop();
225+
ScaffoldMessenger.of(context).showSnackBar(
226+
const SnackBar(content: Text('连接已保存')),
227+
);
228+
}
229+
} catch (e) {
230+
if (mounted) {
231+
ScaffoldMessenger.of(context).showSnackBar(
232+
SnackBar(content: Text('保存失败: $e')),
233+
);
234+
}
235+
} finally {
236+
if (mounted) {
237+
setState(() {
238+
_isConnecting = false;
239+
});
240+
}
241+
}
242+
}
243+
171244
void _showConnectionError(String error) {
172245
showDialog(
173246
context: context,
@@ -200,23 +273,59 @@ class _QuickConnectDialogState extends State<QuickConnectDialog> {
200273
).then((_) => _loadCredentials());
201274
}
202275

276+
// 获取对话框标题
277+
String _getDialogTitle() {
278+
if (widget.isNewConnection) return '新建连接';
279+
if (_isEditing) return '编辑连接';
280+
return '快速连接';
281+
}
282+
283+
// 获取操作按钮文本
284+
String _getActionButtonText() {
285+
if (widget.isNewConnection) return '保存';
286+
if (_isEditing) return '更新';
287+
return '连接';
288+
}
289+
203290
@override
204291
Widget build(BuildContext context) {
205292
return AlertDialog(
206-
title: Text(_isEditing ? '编辑连接' : '快速连接'),
293+
title: Text(_getDialogTitle()),
207294
content: SingleChildScrollView(
208295
child: Form(
209296
key: _formKey,
210297
child: Column(
211298
mainAxisSize: MainAxisSize.min,
212299
children: [
300+
// 连接名称字段
301+
TextFormField(
302+
controller: _nameController,
303+
decoration: InputDecoration(
304+
labelText: '连接名称',
305+
hintText: '请输入连接名称',
306+
suffixIcon: !_isEditing ? IconButton(
307+
icon: const Icon(Icons.autorenew),
308+
onPressed: _generateConnectionName,
309+
tooltip: '自动生成名称',
310+
) : null,
311+
),
312+
validator: (value) {
313+
if (value == null || value.isEmpty) {
314+
return '请输入连接名称';
315+
}
316+
return null;
317+
},
318+
),
319+
const SizedBox(height: 16),
320+
213321
// 主机地址
214322
TextFormField(
215323
controller: _hostController,
216324
decoration: const InputDecoration(
217325
labelText: '主机地址',
218326
hintText: '例如:192.168.1.1',
219327
),
328+
onChanged: !_isEditing ? (value) => _generateConnectionName() : null,
220329
validator: (value) {
221330
if (value == null || value.isEmpty) {
222331
return '请输入主机地址';
@@ -233,6 +342,7 @@ class _QuickConnectDialogState extends State<QuickConnectDialog> {
233342
labelText: '端口号',
234343
),
235344
keyboardType: TextInputType.number,
345+
onChanged: !_isEditing ? (value) => _generateConnectionName() : null,
236346
validator: (value) {
237347
if (value == null || value.isEmpty) {
238348
return '请输入端口号';
@@ -284,7 +394,7 @@ class _QuickConnectDialogState extends State<QuickConnectDialog> {
284394
),
285395
const SizedBox(height: 16),
286396

287-
// 连接类型 - 修复默认值问题
397+
// 连接类型
288398
DropdownButtonFormField<ConnectionType>(
289399
value: _selectedType,
290400
decoration: const InputDecoration(
@@ -304,20 +414,18 @@ class _QuickConnectDialogState extends State<QuickConnectDialog> {
304414
),
305415
const SizedBox(height: 16),
306416

307-
308-
CheckboxListTile(
309-
title: const Text('记住该连接'),
310-
value: _isEditing ? true : _rememberConnection,
311-
onChanged: _isEditing
312-
? null
313-
: (value) {
314-
setState(() {
315-
_rememberConnection = value!;
316-
});
317-
},
318-
controlAffinity: ListTileControlAffinity.leading,
319-
),
320-
417+
// 记住连接复选框 - 只在快速连接模式显示
418+
if (!widget.isNewConnection && !_isEditing)
419+
CheckboxListTile(
420+
title: const Text('记住该连接'),
421+
value: _rememberConnection,
422+
onChanged: (value) {
423+
setState(() {
424+
_rememberConnection = value!;
425+
});
426+
},
427+
controlAffinity: ListTileControlAffinity.leading,
428+
),
321429
],
322430
),
323431
),
@@ -329,10 +437,12 @@ class _QuickConnectDialogState extends State<QuickConnectDialog> {
329437
),
330438
ElevatedButton(
331439
onPressed: _isConnecting ? null : () {
332-
if (_isEditing) {
333-
_updateConnection();
440+
if (widget.isNewConnection) {
441+
_saveConnectionOnly(); // 新建连接:仅保存
442+
} else if (_isEditing) {
443+
_updateConnection(); // 编辑连接:更新
334444
} else {
335-
_connectToServer();
445+
_connectToServer(); // 快速连接:连接
336446
}
337447
},
338448
child: _isConnecting
@@ -341,7 +451,7 @@ class _QuickConnectDialogState extends State<QuickConnectDialog> {
341451
height: 16,
342452
child: CircularProgressIndicator(strokeWidth: 2),
343453
)
344-
: Text(_isEditing ? '更新' : '连接'),
454+
: Text(_getActionButtonText()),
345455
),
346456
],
347457
);

0 commit comments

Comments
 (0)