Skip to content

Commit cc28194

Browse files
committed
调整代理设置页面,对齐webdav。
1 parent 9296e62 commit cc28194

File tree

6 files changed

+282
-303
lines changed

6 files changed

+282
-303
lines changed

lib/pages/my/my_page.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ class _MyPageState extends State<MyPage> {
9898
),
9999
SettingsTile.navigation(
100100
onPressed: (_) {
101-
Modular.to.pushNamed('/settings/player/proxy');
101+
Modular.to.pushNamed('/settings/proxy');
102102
},
103103
leading: const Icon(Icons.vpn_key_rounded),
104104
title: Text('代理设置', style: TextStyle(fontFamily: fontFamily)),
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:kazumi/bean/dialog/dialog_helper.dart';
3+
import 'package:hive/hive.dart';
4+
import 'package:kazumi/bean/appbar/sys_app_bar.dart';
5+
import 'package:kazumi/utils/storage.dart';
6+
import 'package:kazumi/utils/proxy_utils.dart';
7+
import 'package:kazumi/utils/proxy_manager.dart';
8+
import 'package:kazumi/request/request.dart';
9+
10+
class ProxyEditorPage extends StatefulWidget {
11+
const ProxyEditorPage({super.key});
12+
13+
@override
14+
State<ProxyEditorPage> createState() => _ProxyEditorPageState();
15+
}
16+
17+
class _ProxyEditorPageState extends State<ProxyEditorPage> {
18+
Box setting = GStorage.setting;
19+
final _formKey = GlobalKey<FormState>();
20+
final TextEditingController urlController = TextEditingController();
21+
final TextEditingController usernameController = TextEditingController();
22+
final TextEditingController passwordController = TextEditingController();
23+
bool passwordVisible = false;
24+
25+
@override
26+
void initState() {
27+
super.initState();
28+
urlController.text =
29+
setting.get(SettingBoxKey.proxyUrl, defaultValue: '');
30+
usernameController.text =
31+
setting.get(SettingBoxKey.proxyUsername, defaultValue: '');
32+
passwordController.text =
33+
setting.get(SettingBoxKey.proxyPassword, defaultValue: '');
34+
}
35+
36+
@override
37+
void dispose() {
38+
urlController.dispose();
39+
usernameController.dispose();
40+
passwordController.dispose();
41+
super.dispose();
42+
}
43+
44+
Future<void> saveAndTest() async {
45+
if (!_formKey.currentState!.validate()) {
46+
return;
47+
}
48+
49+
final url = urlController.text.trim();
50+
if (url.isEmpty) {
51+
KazumiDialog.showToast(message: '请输入代理地址');
52+
return;
53+
}
54+
55+
await setting.put(SettingBoxKey.proxyUrl, url);
56+
await setting.put(SettingBoxKey.proxyUsername, usernameController.text);
57+
await setting.put(SettingBoxKey.proxyPassword, passwordController.text);
58+
59+
KazumiDialog.showToast(message: '配置已保存,开始测试');
60+
61+
final proxyEnable =
62+
setting.get(SettingBoxKey.proxyEnable, defaultValue: false);
63+
if (!proxyEnable) {
64+
await setting.put(SettingBoxKey.proxyEnable, true);
65+
}
66+
ProxyManager.applyProxy();
67+
68+
try {
69+
final response = await Request().get(
70+
'https://www.google.com',
71+
extra: {'customError': true},
72+
shouldRethrow: true,
73+
);
74+
if (response.statusCode == 200) {
75+
KazumiDialog.showToast(message: '测试成功');
76+
} else {
77+
KazumiDialog.showToast(message: '测试失败: HTTP ${response.statusCode}');
78+
if (!proxyEnable) {
79+
await setting.put(SettingBoxKey.proxyEnable, false);
80+
ProxyManager.clearProxy();
81+
}
82+
}
83+
} catch (e) {
84+
KazumiDialog.showToast(message: '测试失败: $e');
85+
if (!proxyEnable) {
86+
await setting.put(SettingBoxKey.proxyEnable, false);
87+
ProxyManager.clearProxy();
88+
}
89+
}
90+
}
91+
92+
@override
93+
Widget build(BuildContext context) {
94+
return Scaffold(
95+
appBar: const SysAppBar(title: Text('代理配置')),
96+
body: SingleChildScrollView(
97+
padding: const EdgeInsets.all(16.0),
98+
child: Center(
99+
child: SizedBox(
100+
width: (MediaQuery.of(context).size.width > 800) ? 800 : null,
101+
child: Form(
102+
key: _formKey,
103+
child: Column(
104+
children: [
105+
TextFormField(
106+
controller: urlController,
107+
decoration: const InputDecoration(
108+
labelText: '代理地址',
109+
hintText: 'http://127.0.0.1:7890',
110+
border: OutlineInputBorder(),
111+
),
112+
validator: (value) {
113+
if (value == null || value.isEmpty) {
114+
return '请输入代理地址';
115+
}
116+
if (!ProxyUtils.isValidProxyUrl(value)) {
117+
return '格式错误,请使用 http://host:port 格式';
118+
}
119+
return null;
120+
},
121+
),
122+
const SizedBox(height: 20),
123+
TextFormField(
124+
controller: usernameController,
125+
decoration: const InputDecoration(
126+
labelText: '用户名(可选)',
127+
border: OutlineInputBorder(),
128+
),
129+
),
130+
const SizedBox(height: 20),
131+
TextFormField(
132+
controller: passwordController,
133+
obscureText: !passwordVisible,
134+
decoration: InputDecoration(
135+
labelText: '密码(可选)',
136+
border: const OutlineInputBorder(),
137+
suffixIcon: IconButton(
138+
onPressed: () {
139+
setState(() {
140+
passwordVisible = !passwordVisible;
141+
});
142+
},
143+
icon: Icon(passwordVisible
144+
? Icons.visibility_rounded
145+
: Icons.visibility_off_rounded),
146+
),
147+
),
148+
),
149+
],
150+
),
151+
),
152+
),
153+
),
154+
),
155+
floatingActionButton: FloatingActionButton.extended(
156+
onPressed: saveAndTest,
157+
icon: const Icon(Icons.save),
158+
label: const Text('保存并测试'),
159+
),
160+
);
161+
}
162+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import 'package:kazumi/pages/settings/proxy/proxy_settings_page.dart';
2+
import 'package:kazumi/pages/settings/proxy/proxy_editor_page.dart';
3+
import 'package:flutter_modular/flutter_modular.dart';
4+
5+
class ProxyModule extends Module {
6+
@override
7+
void binds(i) {}
8+
9+
@override
10+
void routes(r) {
11+
r.child("/", child: (_) => const ProxySettingsPage());
12+
r.child("/editor", child: (_) => const ProxyEditorPage());
13+
}
14+
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:kazumi/bean/dialog/dialog_helper.dart';
3+
import 'package:hive/hive.dart';
4+
import 'package:flutter_modular/flutter_modular.dart';
5+
import 'package:kazumi/bean/appbar/sys_app_bar.dart';
6+
import 'package:kazumi/utils/storage.dart';
7+
import 'package:kazumi/utils/proxy_manager.dart';
8+
import 'package:card_settings_ui/card_settings_ui.dart';
9+
10+
class ProxySettingsPage extends StatefulWidget {
11+
const ProxySettingsPage({super.key});
12+
13+
@override
14+
State<ProxySettingsPage> createState() => _ProxySettingsPageState();
15+
}
16+
17+
class _ProxySettingsPageState extends State<ProxySettingsPage> {
18+
Box setting = GStorage.setting;
19+
late bool proxyEnable;
20+
21+
@override
22+
void initState() {
23+
super.initState();
24+
proxyEnable = setting.get(SettingBoxKey.proxyEnable, defaultValue: false);
25+
}
26+
27+
void onBackPressed(BuildContext context) {
28+
if (KazumiDialog.observer.hasKazumiDialog) {
29+
KazumiDialog.dismiss();
30+
return;
31+
}
32+
}
33+
34+
Future<void> updateProxyEnable(bool value) async {
35+
if (value) {
36+
final proxyUrl = setting.get(SettingBoxKey.proxyUrl, defaultValue: '');
37+
if (proxyUrl.isEmpty) {
38+
KazumiDialog.showToast(message: '请先配置代理地址');
39+
return;
40+
}
41+
}
42+
43+
await setting.put(SettingBoxKey.proxyEnable, value);
44+
setState(() {
45+
proxyEnable = value;
46+
});
47+
48+
if (value) {
49+
ProxyManager.applyProxy();
50+
KazumiDialog.showToast(message: '代理已启用');
51+
} else {
52+
ProxyManager.clearProxy();
53+
KazumiDialog.showToast(message: '代理已禁用');
54+
}
55+
}
56+
57+
@override
58+
Widget build(BuildContext context) {
59+
final fontFamily = Theme.of(context).textTheme.bodyMedium?.fontFamily;
60+
return PopScope(
61+
canPop: true,
62+
onPopInvokedWithResult: (bool didPop, Object? result) {
63+
onBackPressed(context);
64+
},
65+
child: Scaffold(
66+
appBar: const SysAppBar(title: Text('代理设置')),
67+
body: SettingsList(
68+
maxWidth: 800,
69+
sections: [
70+
SettingsSection(
71+
title: Text('代理', style: TextStyle(fontFamily: fontFamily)),
72+
tiles: [
73+
SettingsTile.switchTile(
74+
onToggle: (value) async {
75+
await updateProxyEnable(value ?? !proxyEnable);
76+
},
77+
title:
78+
Text('启用代理', style: TextStyle(fontFamily: fontFamily)),
79+
description: Text('启用后网络请求将通过代理服务器',
80+
style: TextStyle(fontFamily: fontFamily)),
81+
initialValue: proxyEnable,
82+
),
83+
SettingsTile.navigation(
84+
onPressed: (_) async {
85+
await Modular.to.pushNamed('/settings/proxy/editor');
86+
setState(() {
87+
proxyEnable = setting.get(SettingBoxKey.proxyEnable,
88+
defaultValue: false);
89+
});
90+
},
91+
title:
92+
Text('代理配置', style: TextStyle(fontFamily: fontFamily)),
93+
description: Text('配置代理服务器地址和认证信息',
94+
style: TextStyle(fontFamily: fontFamily)),
95+
),
96+
],
97+
),
98+
],
99+
),
100+
),
101+
);
102+
}
103+
}

0 commit comments

Comments
 (0)