Skip to content

Commit 2afde16

Browse files
committed
fix:terminal page name display.add first use check.improve UI for some niche devices
1 parent 08796a1 commit 2afde16

File tree

8 files changed

+139
-41
lines changed

8 files changed

+139
-41
lines changed

README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ A lightweight & cross-platform SSH/SFTP client built with Flutter.
66
- 完整 SSH 终端(快捷键、手势滚动、字号缩放)
77
- 完整 SFTP:批量文件操作,支持自定义默认访问目录
88
- 响应式布局:多尺寸设备自适应
9-
- 跨平台:Android / Windows / iOS(ToDo) / HarmonyOS(ToDo)
9+
- 跨平台:Android / Windows / iOS(ToDo) / HarmonyOS
1010
- 支持私钥 / 密码 认证
1111

1212
### 截图
@@ -17,8 +17,10 @@ A lightweight & cross-platform SSH/SFTP client built with Flutter.
1717
### 下载
1818
| 平台 | 下载 | 备注 |
1919
|------|------|------|
20-
| Android | [APK](https://github.com/RWPteam/connecter/releases/download/1.0Beta5/1.0Beta5_android_arm64.apk) | arm64-v8a,更多架构查看Release |
21-
| Windows | [exe](https://github.com/RWPteam/connecter/releases/download/1.0Beta5/1.0Beta5_windows_x64.exe) | 仅支持64位设备 |
20+
| Android | [APK](https://github.com/RWPteam/connecter/releases/download/1.0/Release_android.apk) | arm&arm64 |
21+
| Windows | [exe](https://github.com/RWPteam/connecter/releases/download/1.0/Release_windows.exe) | 仅支持64位设备 |
22+
| OHOS | [app](https://github.com/RWPteam/connecter/releases/download/1.0/Release_ohos.app) | 应用市场正在审核中 |
23+
2224

2325
### 构建&打包
2426
* 需注意,本项目使用了修改过的[xterm.dart](https://github.com/samu1oto/xterm.dart)以添加快捷操作栏等功能
@@ -37,7 +39,7 @@ flutter run -d <device_id>
3739
flutter build apk --split-per-abi
3840
# Windows
3941
flutter build windows
40-
# HarmonyOS
42+
# HarmonyOS 请使用https://github.com/samu1oto/connecter-ohos/tree/ohos
4143
flutter build hap
4244
# or
4345
flutter build app

android/app/build.gradle

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
2323

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

2929
def flutterVersionName = "1.0Beta5"
@@ -63,6 +63,9 @@ android {
6363
targetSdk = flutter.targetSdkVersion
6464
versionCode = flutterVersionCode.toInteger()
6565
versionName = flutterVersionName
66+
ndk {
67+
abiFilters 'arm64-v8a', 'armeabi-v7a'
68+
}
6669
}
6770

6871
buildTypes {

lib/help_page.dart

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ class HelpPage extends StatelessWidget {
55

66
@override
77
Widget build(BuildContext context) {
8+
89
return Scaffold(
910
appBar: AppBar(
1011
title: const Text('帮助'),
@@ -19,7 +20,7 @@ class HelpPage extends StatelessWidget {
1920
crossAxisAlignment: CrossAxisAlignment.start,
2021
children: [
2122
const Text(
22-
'欢迎使用 Connecter!',
23+
'Connecter 帮助',
2324
style: TextStyle(
2425
fontSize: 24,
2526
fontWeight: FontWeight.bold,
@@ -41,33 +42,27 @@ class HelpPage extends StatelessWidget {
4142
),
4243
_buildHelpSection(
4344
title: 'SSH页面',
44-
content: '安卓设备点击空白处可唤起输入法,Windows可直接进行输入',
45-
),
46-
_buildHelpSection(
47-
title: 'SSH快捷键',
48-
content: '目前已经支持Windows平台 Ctrl+Shift+A全选 Ctrl+Shift+C复制 Ctrl+Shift+V粘贴,安卓端复制粘贴逻辑尚在开发中',
45+
content: '点击空白处可唤起输入法,外接键盘可用Ctrl+Shift+C/V/A快捷键',
4946
),
5047
_buildHelpSection(
5148
title: 'SFTP页面',
52-
content: '在顶部进行文件操作,安卓端可以使用侧滑返回',
49+
content: '在顶部进行文件操作,可以使用侧滑返回',
5350
),
5451
_buildHelpSection(
5552
title: '反馈',
56-
content: '如有问题或建议,请在github页面发布issue',
53+
content: '如有问题或建议,请发送邮件至samuioto@outlook.com',
5754
),
5855
const SizedBox(height: 24),
59-
Center(
60-
child: ElevatedButton(
56+
OutlinedButton(
6157
onPressed: () {
6258
showAboutDialog(
6359
context: context,
6460
applicationName: 'connecter',
65-
applicationVersion: '1.0 Beta 5',
61+
applicationVersion: '1.0.0',
6662
);
6763
},
6864
child: const Text('关于'),
6965
),
70-
),
7166
],
7267
),
7368
),
@@ -95,3 +90,4 @@ class HelpPage extends StatelessWidget {
9590
);
9691
}
9792
}
93+

lib/main_page.dart

Lines changed: 95 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
// ignore_for_file: use_build_context_synchronously
22
import 'dart:async';
33
import 'dart:io';
4+
import 'package:connecter/help_page.dart';
45
import 'package:connecter/setting_page.dart';
56
import 'package:flutter/material.dart';
67
import 'manage_connections_page.dart';
78
import 'manage_credentials_page.dart';
89
import 'quick_connect_dialog.dart';
910
import 'models/connection_model.dart';
11+
import 'services/setting_service.dart';
1012
import 'services/storage_service.dart';
1113
import 'services/ssh_service.dart';
1214
import 'terminal_page.dart';
@@ -28,13 +30,25 @@ class _MainPageState extends State<MainPage> {
2830
bool _isConnecting = false;
2931
ConnectionInfo? _connectingConnection;
3032
bool _permissionsGranted = false;
33+
final SettingsService _settingsService = SettingsService();
34+
bool _isFirstRun = true;
3135

3236
@override
3337
void initState() {
3438
super.initState();
35-
_checkAndRequestPermissions();
39+
if (Platform.isAndroid) {
40+
_checkAndRequestPermissions();
41+
} else {
42+
setState(() {
43+
_permissionsGranted = true;
44+
});
45+
_loadRecentConnections();
46+
_checkFirstRun();
47+
}
3648
}
3749

50+
51+
3852
Future<void> _checkAndRequestPermissions() async {
3953
final storageStatus = await Permission.storage.status;
4054
final storageStatusHigh = await Permission.manageExternalStorage.status;
@@ -121,6 +135,68 @@ class _MainPageState extends State<MainPage> {
121135
exit(0);
122136
}
123137

138+
Future<void> _checkFirstRun() async {
139+
final settings = await _settingsService.getSettings();
140+
setState(() {
141+
_isFirstRun = settings.isFirstRun;
142+
});
143+
144+
if (_isFirstRun) {
145+
_showWelcome();
146+
_settingsService.markAsNotFirstRun();
147+
}
148+
}
149+
150+
151+
152+
void _showWelcome() {
153+
WidgetsBinding.instance.addPostFrameCallback((_) {
154+
showDialog(
155+
context: context,
156+
barrierDismissible: false,
157+
builder: (context) => AlertDialog(
158+
title: const Text('欢迎使用Connecter'),
159+
content: Column(
160+
mainAxisSize: MainAxisSize.min,
161+
crossAxisAlignment: CrossAxisAlignment.start,
162+
children: [
163+
const Text('看起来您是第一次使用该应用'),
164+
const SizedBox(height: 8),
165+
MouseRegion(
166+
cursor: SystemMouseCursors.click,
167+
child: GestureDetector(
168+
onTap: _showHelp,
169+
child: const Text(
170+
'点击查看帮助',
171+
style: TextStyle(
172+
color: Colors.blueAccent,
173+
),
174+
),
175+
),
176+
),
177+
],
178+
),
179+
actions: [
180+
TextButton(
181+
onPressed: () => Navigator.of(context).pop(),
182+
child: const Text('关闭'),
183+
),
184+
],
185+
),
186+
);
187+
});
188+
}
189+
190+
void _showHelp() {
191+
192+
Navigator.of(context).push(
193+
MaterialPageRoute(
194+
builder: (context) => const HelpPage(),
195+
),
196+
);
197+
}
198+
199+
124200
Future<void> _loadRecentConnections() async {
125201
try {
126202
final recentConnections = await _storageService.getRecentConnections();
@@ -710,9 +786,9 @@ Future<void> _performConnection(ConnectionInfo connection) async {
710786
);
711787

712788
await sshService.connect(connection, credential)
713-
.timeout(const Duration(seconds: 3), onTimeout: () {
714-
throw TimeoutException('连接超时,请检查网络或主机是否可达');
715-
});
789+
.timeout(const Duration(seconds: 3),); //onTimeout: () {
790+
//throw TimeoutException('连接超时,请检查网络或主机是否可达');
791+
//});
716792

717793
// 添加到最近连接(不等待完成),不然巨卡无比
718794
unawaited (storageService.addRecentConnection(connection));
@@ -766,12 +842,14 @@ void _handleConnectionError(ConnectionInfo connection, String error) {
766842
);
767843
}
768844

845+
769846
List<Widget> _buildButtons(
770847
BuildContext context,
771848
bool showSubtitle,
772849
double screenHeight,
773850
) {
774-
const double buttonHeight = 100;
851+
// 根据屏幕高度动态计算按钮高度
852+
final double buttonHeight = screenHeight >= 500 ? 100 : 80;
775853

776854
Widget buildButton({
777855
required VoidCallback onPressed,
@@ -787,16 +865,16 @@ void _handleConnectionError(ConnectionInfo connection, String error) {
787865
children: [
788866
Text(
789867
title,
790-
style: const TextStyle(
791-
fontSize: 18,
868+
style: TextStyle(
869+
fontSize: screenHeight >= 500 ? 18 : 16, // 根据高度调整字体大小
792870
fontWeight: FontWeight.bold,
793871
),
794872
),
795873
const SizedBox(height: 4),
796874
Text(
797875
subtitle,
798-
style: const TextStyle(
799-
fontSize: 14,
876+
style: TextStyle(
877+
fontSize: screenHeight >= 500 ? 14 : 12, // 根据高度调整字体大小
800878
color: Colors.grey,
801879
),
802880
),
@@ -807,20 +885,20 @@ void _handleConnectionError(ConnectionInfo connection, String error) {
807885
padding: const EdgeInsets.only(left: 8.0),
808886
child: Text(
809887
title,
810-
style: const TextStyle(
811-
fontSize: 18,
888+
style: TextStyle(
889+
fontSize: screenHeight >= 500 ? 18 : 16, // 根据高度调整字体大小
812890
fontWeight: FontWeight.bold,
813891
),
814892
),
815893
);
816894

817895
return SizedBox(
818896
width: double.infinity,
819-
height: buttonHeight,
897+
height: buttonHeight, // 使用动态计算的高度
820898
child: OutlinedButton(
821899
onPressed: onPressed,
822900
style: OutlinedButton.styleFrom(
823-
padding: const EdgeInsets.all(14),
901+
padding: EdgeInsets.all(screenHeight >= 500 ? 14 : 12), // 根据高度调整内边距
824902
shape: RoundedRectangleBorder(
825903
borderRadius: BorderRadius.circular(12),
826904
),
@@ -846,7 +924,6 @@ void _handleConnectionError(ConnectionInfo connection, String error) {
846924
},
847925
title: '快速连接',
848926
subtitle: '输入地址和凭证快速建立连接',
849-
850927
),
851928
const SizedBox(height: 16),
852929

@@ -875,17 +952,16 @@ void _handleConnectionError(ConnectionInfo connection, String error) {
875952
),
876953
);
877954
},
878-
879955
title: '管理认证凭证',
880956
subtitle: '管理密码和证书凭证',
881957
),
882958
const SizedBox(height: 16),
883959
buildButton(
884960
onPressed: () {
885-
Navigator.push(
886-
context,
887-
MaterialPageRoute(builder: (context) => const SettingsPage()),
888-
);
961+
Navigator.push(
962+
context,
963+
MaterialPageRoute(builder: (context) => const SettingsPage()),
964+
);
889965
},
890966
title: "设置",
891967
subtitle: "查看设置、使用说明和版本信息",

lib/models/app_settings_model.dart

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,47 @@
11
class AppSettings {
22
final String? defaultSftpPath;
33
final String? defaultDownloadPath;
4+
final bool isFirstRun;
45

56
const AppSettings({
67
this.defaultSftpPath,
78
this.defaultDownloadPath,
9+
this.isFirstRun = true,
810
});
911

1012
AppSettings copyWith({
1113
String? defaultSftpPath,
1214
String? defaultDownloadPath,
15+
bool? isFirstRun,
1316
}) {
1417
return AppSettings(
1518
defaultSftpPath: defaultSftpPath ?? this.defaultSftpPath,
1619
defaultDownloadPath: defaultDownloadPath ?? this.defaultDownloadPath,
20+
isFirstRun: isFirstRun ?? this.isFirstRun,
1721
);
1822
}
1923

2024
Map<String, dynamic> toMap() {
2125
return {
2226
'defaultSftpPath': defaultSftpPath,
2327
'defaultDownloadPath': defaultDownloadPath,
28+
'isFirstRun': isFirstRun,
2429
};
2530
}
2631

2732
factory AppSettings.fromMap(Map<String, dynamic> map) {
2833
return AppSettings(
2934
defaultSftpPath: map['defaultSftpPath'],
3035
defaultDownloadPath: map['defaultDownloadPath'],
36+
isFirstRun: map['isFirstRun'] ?? true,
3137
);
3238
}
3339

3440
static AppSettings get defaults {
3541
return const AppSettings(
3642
defaultSftpPath: '/',
37-
defaultDownloadPath: null,
43+
defaultDownloadPath: null,
44+
isFirstRun: true,
3845
);
3946
}
4047
}

0 commit comments

Comments
 (0)