Skip to content

Commit 155d9b5

Browse files
committed
[ver1.2.3] support sudo. Closes #23.
1 parent 717ec24 commit 155d9b5

File tree

20 files changed

+1712
-700
lines changed

20 files changed

+1712
-700
lines changed

android/app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
2323

2424
def flutterVersionCode = localProperties.getProperty("flutter.versionCode")
2525
if (flutterVersionCode == null) {
26-
flutterVersionCode = "213"
26+
flutterVersionCode = "232"
2727
}
2828

29-
def flutterVersionName = "1.2.2"
29+
def flutterVersionName = "1.2.3"
3030
//def flutterVersionName = localProperties.getProperty("flutter.versionName")
3131
//if (flutterVersionName == null) {
3232
// flutterVersionName = "1.0Beta3"

assets/data.png

-137 KB
Binary file not shown.

assets/keygen.png

-118 KB
Binary file not shown.

lib/components/file_editor.dart

Lines changed: 13 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,19 @@
11
// ignore_for_file: use_build_context_synchronously
22

33
import 'dart:convert';
4-
import 'dart:typed_data';
54
import 'dart:async';
5+
import 'package:flutter/foundation.dart';
66
import 'package:flutter/material.dart';
77
import 'package:code_text_field/code_text_field.dart';
8-
9-
// --- 核心语言包 ---
108
import 'package:highlight/languages/dart.dart';
119
import 'package:highlight/languages/javascript.dart';
1210
import 'package:highlight/languages/python.dart';
1311
import 'package:highlight/languages/java.dart';
1412
import 'package:highlight/languages/cpp.dart';
1513
import 'package:highlight/languages/yaml.dart';
1614
import 'package:highlight/languages/bash.dart';
17-
// --- 新增语言支持 ---
1815
import 'package:highlight/languages/json.dart';
19-
import 'package:highlight/languages/xml.dart'; // 支持 HTML 和 XML
16+
import 'package:highlight/languages/xml.dart';
2017
import 'package:highlight/languages/css.dart';
2118
import 'package:highlight/languages/markdown.dart';
2219
import 'package:highlight/languages/go.dart';
@@ -26,8 +23,6 @@ import 'package:highlight/languages/sql.dart';
2623
import 'package:highlight/languages/kotlin.dart';
2724
import 'package:highlight/languages/swift.dart';
2825
import 'package:highlight/languages/makefile.dart';
29-
30-
// 高亮主题
3126
import 'package:flutter_highlight/themes/monokai-sublime.dart';
3227
import 'package:flutter_highlight/themes/github.dart';
3328

@@ -55,17 +50,19 @@ class _FileEditorPageState extends State<FileEditorPage> {
5550
bool _isModified = false;
5651
bool _isSaving = false;
5752
bool _showSearch = false;
53+
bool get ismobile =>
54+
defaultTargetPlatform == TargetPlatform.android ||
55+
defaultTargetPlatform == TargetPlatform.ohos ||
56+
defaultTargetPlatform == TargetPlatform.iOS;
5857

5958
final TextEditingController _findController = TextEditingController();
6059
final TextEditingController _replaceController = TextEditingController();
6160

62-
// 历史记录栈
6361
final List<String> _history = [];
6462
int _historyIndex = -1;
6563
bool _isIgnoringListener = false;
6664
Timer? _historyTimer;
6765

68-
// 扩展后的语言字典
6966
final Map<String, dynamic> _languages = {
7067
'Bash': bash,
7168
'C++': cpp,
@@ -92,7 +89,6 @@ class _FileEditorPageState extends State<FileEditorPage> {
9289
@override
9390
void initState() {
9491
super.initState();
95-
// 根据后缀名简单初始化语言逻辑(可选)
9692
_currentLangKey = _detectLanguage(widget.filename);
9793

9894
_codeController = CodeController(
@@ -105,7 +101,6 @@ class _FileEditorPageState extends State<FileEditorPage> {
105101
_codeController.addListener(_handleTextChange);
106102
}
107103

108-
// 自动根据后缀识别语言
109104
String _detectLanguage(String filename) {
110105
String ext = filename.split('.').last.toLowerCase();
111106
switch (ext) {
@@ -146,8 +141,6 @@ class _FileEditorPageState extends State<FileEditorPage> {
146141
}
147142
}
148143

149-
// --- 逻辑处理 ---
150-
151144
void _handleTextChange() {
152145
if (_isIgnoringListener) return;
153146
if (!_isModified && _codeController.text != widget.initialContent) {
@@ -181,8 +174,6 @@ class _FileEditorPageState extends State<FileEditorPage> {
181174
}
182175
}
183176

184-
// --- 样式辅助 ---
185-
186177
Color _getAppBarColor() {
187178
return Theme.of(context).brightness == Brightness.dark
188179
? const Color(0xFF1E1E1E)
@@ -192,7 +183,6 @@ class _FileEditorPageState extends State<FileEditorPage> {
192183
@override
193184
Widget build(BuildContext context) {
194185
final isDark = Theme.of(context).brightness == Brightness.dark;
195-
final isMobile = MediaQuery.of(context).size.width < 600;
196186

197187
return PopScope(
198188
canPop: false,
@@ -204,21 +194,20 @@ class _FileEditorPageState extends State<FileEditorPage> {
204194
},
205195
child: Scaffold(
206196
backgroundColor: isDark ? const Color(0xFF1E1E1E) : Colors.white,
207-
// 1. 高度定制的 AppBar
208197
appBar: AppBar(
209198
toolbarHeight: 40,
210199
backgroundColor: _getAppBarColor(),
211200
foregroundColor: Colors.white,
212201
titleSpacing: 0,
213202
automaticallyImplyLeading: false,
214-
leading: isMobile
203+
leading: ismobile
215204
? null
216205
: IconButton(
217206
icon: const Icon(Icons.arrow_back, size: 20),
218207
onPressed: () => Navigator.of(context).pop(),
219208
),
220209
title: Padding(
221-
padding: EdgeInsets.only(left: isMobile ? 18.0 : 0),
210+
padding: EdgeInsets.only(left: ismobile ? 18.0 : 0),
222211
child: Column(
223212
mainAxisAlignment: MainAxisAlignment.center,
224213
crossAxisAlignment: CrossAxisAlignment.start,
@@ -234,7 +223,9 @@ class _FileEditorPageState extends State<FileEditorPage> {
234223
children: [
235224
Icon(
236225
_isModified ? Icons.circle : Icons.circle_outlined,
237-
color: _isModified ? Colors.orange : Colors.white70,
226+
color: _isModified
227+
? Theme.of(context).primaryColor
228+
: Colors.white70,
238229
size: 8,
239230
),
240231
const SizedBox(width: 4),
@@ -253,7 +244,6 @@ class _FileEditorPageState extends State<FileEditorPage> {
253244
),
254245
),
255246
actions: [
256-
// 只保留保存按钮
257247
IconButton(
258248
icon: Icon(_isSaving ? Icons.hourglass_empty : Icons.save,
259249
size: 20),
@@ -319,7 +309,6 @@ class _FileEditorPageState extends State<FileEditorPage> {
319309
);
320310
}
321311

322-
// 快捷工具栏
323312
Widget _buildShortcutBar(bool isDark) {
324313
return Container(
325314
height: 38,
@@ -339,8 +328,6 @@ class _FileEditorPageState extends State<FileEditorPage> {
339328
isDark),
340329
_toolBtn(Icons.text_decrease, "", () => setState(() => _fontSize--),
341330
isDark),
342-
343-
// 语言切换下拉
344331
PopupMenuButton<String>(
345332
onSelected: (key) => setState(() {
346333
_currentLangKey = key;
@@ -453,8 +440,8 @@ class _FileEditorPageState extends State<FileEditorPage> {
453440
_isModified = false;
454441
_isSaving = false;
455442
});
456-
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
457-
content: Text('文件已保存'), behavior: SnackBarBehavior.floating));
443+
ScaffoldMessenger.of(context)
444+
.showSnackBar(const SnackBar(content: Text('文件已保存')));
458445
} catch (e) {
459446
setState(() => _isSaving = false);
460447
}

lib/models/connection_model.dart

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ class ConnectionInfo {
99
bool isPinned;
1010
DateTime lastUsed;
1111
String? sftpPath;
12+
String? archive;
1213

1314
ConnectionInfo({
1415
required this.id,
@@ -20,8 +21,9 @@ class ConnectionInfo {
2021
required this.remember,
2122
this.isPinned = false,
2223
this.sftpPath,
24+
this.archive, // 新增
2325
DateTime? lastUsed,
24-
}) : lastUsed = lastUsed ?? DateTime.now(); //定义连接信息模型
26+
}) : lastUsed = lastUsed ?? DateTime.now();
2527

2628
Map<String, dynamic> toJson() {
2729
return {
@@ -35,8 +37,9 @@ class ConnectionInfo {
3537
'isPinned': isPinned,
3638
'lastUsed': lastUsed.toIso8601String(),
3739
'sftpPath': sftpPath,
40+
'archive': archive,
3841
};
39-
} //转换为json
42+
}
4043

4144
factory ConnectionInfo.fromJson(Map<String, dynamic> json) {
4245
ConnectionType type;
@@ -59,13 +62,46 @@ class ConnectionInfo {
5962
remember: json['remember'],
6063
isPinned: json['isPinned'] ?? false,
6164
sftpPath: json['sftpPath'],
65+
archive: json['archive'],
6266
lastUsed: json['lastUsed'] != null
6367
? DateTime.parse(json['lastUsed'])
6468
: DateTime.now(),
6569
);
6670
}
6771
}
6872

73+
class ArchiveGroup {
74+
String id;
75+
String name;
76+
List<String> connectionIds;
77+
bool isExpanded;
78+
79+
ArchiveGroup({
80+
required this.id,
81+
required this.name,
82+
this.connectionIds = const [],
83+
this.isExpanded = true,
84+
});
85+
86+
Map<String, dynamic> toJson() {
87+
return {
88+
'id': id,
89+
'name': name,
90+
'connectionIds': connectionIds,
91+
'isExpanded': isExpanded,
92+
};
93+
}
94+
95+
factory ArchiveGroup.fromJson(Map<String, dynamic> json) {
96+
return ArchiveGroup(
97+
id: json['id'],
98+
name: json['name'],
99+
connectionIds: List<String>.from(json['connectionIds'] ?? []),
100+
isExpanded: json['isExpanded'] ?? true,
101+
);
102+
}
103+
}
104+
69105
enum ConnectionType {
70106
ssh,
71107
sftp,

lib/pages/help.dart

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -51,32 +51,23 @@ class _HelpPageState extends State<HelpPage> {
5151
content: '可以直接编辑服务器上的文件,支持常见文本格式和编码,支持代码高亮',
5252
imagePath: 'assets/textedit.png',
5353
),
54-
HelpItem(
55-
title: '数据面板(Beta)',
56-
content: '此功能可以监控大部分Linux服务器的系统运行数据,但对于部分服务器不起作用。需要您的服务器支持free、awk等命令',
57-
imagePath: 'assets/data.png',
58-
),
59-
HelpItem(
60-
title: '密钥和证书工具',
61-
content: '此功能可以解析证书的颁发者、有效期、算法等信息,也可以生成密钥对并上传到指定服务器的指定目录',
62-
imagePath: 'assets/keygen.png',
63-
),
6454
HelpItem(
6555
title: '关于 & 反馈',
6656
content: '''
67-
ConnSSH 版本 1.2.2
57+
ConnSSH 版本 1.2.3
58+
59+
新年快乐~
6860
6961
此版本更新内容:
7062
7163
新增功能:
72-
快捷栏支持自定义
73-
支持数据备份/还原
64+
服务器页面支持分组
65+
SFTP文件下载支持sudo执行
7466
7567
问题改进:
76-
• 修复了服务器数据面板不兼容多硬盘服务器的问题
77-
• 完整支持了华为设备的文件下载保存功能
78-
• 修复Android10以下设备无法保存文件的问题
79-
• 改进了部分页面设计
68+
• 修复部分页面边框过细的问题
69+
• 修复 #23 帮助界面异常切换的问题
70+
8071
8172
如有问题或建议,请发送邮件至:
8273
samuioto@outlook.com
@@ -93,7 +84,10 @@ samuioto@outlook.com
9384
void initState() {
9485
super.initState();
9586
_pageController = PageController(initialPage: 0);
87+
_startTimer();
88+
}
9689

90+
void _startTimer() {
9791
_timer = Timer.periodic(const Duration(seconds: 10), (timer) {
9892
if (_currentPage < helpItems.length - 1) {
9993
_currentPage++;
@@ -111,6 +105,11 @@ samuioto@outlook.com
111105
});
112106
}
113107

108+
void _resetTimer() {
109+
_timer.cancel();
110+
_startTimer();
111+
}
112+
114113
@override
115114
void dispose() {
116115
_timer.cancel();
@@ -123,9 +122,6 @@ samuioto@outlook.com
123122
return Scaffold(
124123
appBar: AppBar(
125124
title: const Text('帮助'),
126-
//backgroundColor: Colors.transparent,
127-
//elevation: 0,
128-
//foregroundColor: Theme.of(context).colorScheme.onSurface,
129125
),
130126
body: Padding(
131127
padding: const EdgeInsets.all(16.0),
@@ -156,6 +152,8 @@ samuioto@outlook.com
156152
setState(() {
157153
_currentPage = index;
158154
});
155+
// 手动切换时重置计时器
156+
_resetTimer();
159157
},
160158
itemBuilder: (context, index) {
161159
final item = helpItems[index];
@@ -200,6 +198,8 @@ samuioto@outlook.com
200198
duration: const Duration(milliseconds: 500),
201199
curve: Curves.easeInOut,
202200
);
201+
// 手动切换时重置计时器
202+
_resetTimer();
203203
}
204204
: null,
205205
),
@@ -217,6 +217,8 @@ samuioto@outlook.com
217217
duration: const Duration(milliseconds: 500),
218218
curve: Curves.easeInOut,
219219
);
220+
// 手动切换时重置计时器
221+
_resetTimer();
220222
}
221223
: null,
222224
),

0 commit comments

Comments
 (0)