This commit is contained in:
wanghongenpin
2025-10-05 23:49:15 +08:00
parent 46b8d46f45
commit 2986f29a99
9 changed files with 269 additions and 41 deletions

View File

@@ -341,5 +341,10 @@
"automatic": "Automatic",
"manual": "Manual",
"certNotInstalled": "Certificate not installed",
"openNewWindow": "Open New Window"
"openNewWindow": "Open New Window",
"sponsorDonate": "Sponsor / Donate",
"sponsorSupport": "Support ongoing development",
"sponsorThanks": "Thank you for supporting this open-source project by choosing any of the following methods to help its long-term development.",
"sponsorAfdian": "AFDIAN",
"sponsorBuyMeCoffee": "Buy Me a Coffee"
}

View File

@@ -2003,6 +2003,36 @@ abstract class AppLocalizations {
/// In en, this message translates to:
/// **'Open New Window'**
String get openNewWindow;
/// No description provided for @sponsorDonate.
///
/// In en, this message translates to:
/// **'Sponsor / Donate'**
String get sponsorDonate;
/// No description provided for @sponsorSupport.
///
/// In en, this message translates to:
/// **'Support ongoing development'**
String get sponsorSupport;
/// No description provided for @sponsorThanks.
///
/// In en, this message translates to:
/// **'Thank you for supporting this open-source project by choosing any of the following methods to help its long-term development.'**
String get sponsorThanks;
/// No description provided for @sponsorAfdian.
///
/// In en, this message translates to:
/// **'AFDIAN'**
String get sponsorAfdian;
/// No description provided for @sponsorBuyMeCoffee.
///
/// In en, this message translates to:
/// **'Buy Me a Coffee'**
String get sponsorBuyMeCoffee;
}
class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {

View File

@@ -990,4 +990,20 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get openNewWindow => 'Open New Window';
@override
String get sponsorDonate => 'Sponsor / Donate';
@override
String get sponsorSupport => 'Support ongoing development';
@override
String get sponsorThanks =>
'Thank you for supporting this open-source project by choosing any of the following methods to help its long-term development.';
@override
String get sponsorAfdian => 'AFDIAN';
@override
String get sponsorBuyMeCoffee => 'Buy Me a Coffee';
}

View File

@@ -978,6 +978,21 @@ class AppLocalizationsZh extends AppLocalizations {
@override
String get openNewWindow => '新窗口打开';
@override
String get sponsorDonate => '赞助 / 捐赠';
@override
String get sponsorSupport => '支持项目持续开发';
@override
String get sponsorThanks => '感谢支持开源项目,可选择以下任意方式,帮助项目长期发展';
@override
String get sponsorAfdian => '爱发电赞助';
@override
String get sponsorBuyMeCoffee => 'Buy Me a Coffee';
}
/// The translations for Chinese, using the Han script (`zh_Hant`).
@@ -1952,4 +1967,22 @@ class AppLocalizationsZhHant extends AppLocalizationsZh {
@override
String get certNotInstalled => '未安裝憑證';
@override
String get openNewWindow => '新視窗開啟';
@override
String get sponsorDonate => '贊助 / 捐贈';
@override
String get sponsorSupport => '支持項目持續開發';
@override
String get sponsorThanks => '感謝支持開源項目,可選擇以下任意方式,幫助項目長期發展';
@override
String get sponsorAfdian => '愛發電贊助';
@override
String get sponsorBuyMeCoffee => 'Buy Me a Coffee';
}

View File

@@ -341,5 +341,10 @@
"manual": "手动安装",
"certNotInstalled": "证书未安装",
"openNewWindow": "新窗口打开"
"openNewWindow": "新窗口打开",
"sponsorDonate": "赞助 / 捐赠",
"sponsorSupport": "支持项目持续开发",
"sponsorThanks": "感谢支持开源项目,可选择以下任意方式,帮助项目长期发展",
"sponsorAfdian": "爱发电赞助",
"sponsorBuyMeCoffee": "Buy Me a Coffee"
}

View File

@@ -318,5 +318,11 @@
"automatic": "自動",
"manual": "手動",
"certNotInstalled": "未安裝憑證"
"certNotInstalled": "未安裝憑證",
"openNewWindow": "新視窗開啟",
"sponsorDonate": "贊助 / 捐贈",
"sponsorSupport": "支持項目持續開發",
"sponsorThanks": "感謝支持開源項目,可選擇以下任意方式,幫助項目長期發展",
"sponsorAfdian": "愛發電贊助",
"sponsorBuyMeCoffee": "Buy Me a Coffee"
}

View File

@@ -1,3 +1,4 @@
import 'dart:ui' show FontFeature;
import 'package:flutter/material.dart';
import 'package:proxypin/l10n/app_localizations.dart';
import 'package:proxypin/ui/app_update/app_update_repository.dart';
@@ -29,54 +30,126 @@ class _AppUpdateStateChecking extends State<DesktopAbout> {
const Expanded(child: SizedBox()),
Text(localizations.about, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w500)),
const Expanded(child: SizedBox()),
Align(alignment: Alignment.topRight, child: CloseButton())
const Align(alignment: Alignment.topRight, child: CloseButton())
]),
content: SizedBox(
width: 360,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text("ProxyPin", style: TextStyle(fontSize: 20)),
const Text("ProxyPin", style: TextStyle(fontSize: 20, fontWeight: FontWeight.w600, letterSpacing: .5)),
const SizedBox(height: 10),
Padding(
padding: const EdgeInsets.only(left: 10, right: 10),
child:
Text(isCN ? "全平台开源免费抓包软件" : "Full platform open source free capture HTTP(S) traffic software")),
const SizedBox(height: 10),
Text("Version ${AppConfiguration.version}"),
child: Text(isCN ? "全平台开源免费抓包软件" : "Full platform open source free capture HTTP(S) traffic software",
textAlign: TextAlign.center, style: const TextStyle(height: 1.3))),
const SizedBox(height: 10),
DecoratedBox(
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surfaceContainerHighest.withValues(alpha: 0.4),
borderRadius: BorderRadius.circular(8),
),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
child: Text("Version ${AppConfiguration.version}",
style: TextStyle(
fontWeight: FontWeight.w500,
color: Theme.of(context).colorScheme.primary,
fontFeatures: const [FontFeature.tabularFigures()])),
),
),
const SizedBox(height: 12),
Divider(height: 1, color: Theme.of(context).dividerColor.withValues(alpha: 0.4)),
ListTile(
title: Text('GitHub'),
trailing: const Icon(Icons.open_in_new, size: 22),
onTap: () => launchUrl(Uri.parse(gitHub))),
dense: true,
title: const Text('GitHub'),
trailing: const Icon(Icons.open_in_new, size: 21),
onTap: () => _safeLaunch(Uri.parse(gitHub))),
ListTile(
dense: true,
title: Text(localizations.feedback),
trailing: const Icon(Icons.open_in_new, size: 22),
onTap: () => launchUrl(Uri.parse("$gitHub/issues"))),
trailing: const Icon(Icons.open_in_new, size: 21),
onTap: () => _safeLaunch(Uri.parse("$gitHub/issues"))),
ListTile(
dense: true,
title: Text(localizations.appUpdateCheckVersion),
trailing: checkUpdating
? const SizedBox(width: 22, height: 22, child: CircularProgressIndicator())
: const Icon(Icons.sync, size: 22),
? const SizedBox(width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2))
: const Icon(Icons.sync, size: 21),
onTap: () async {
if (checkUpdating) {
return;
}
setState(() {
checkUpdating = true;
});
if (checkUpdating) return;
setState(() => checkUpdating = true);
await AppUpdateRepository.checkUpdate(context, canIgnore: false, showToast: true);
setState(() {
checkUpdating = false;
});
if (mounted) setState(() => checkUpdating = false);
}),
ListTile(
dense: true,
title: Text(isCN ? "下载地址" : "Download"),
trailing: const Icon(Icons.open_in_new, size: 22),
onTap: () => launchUrl(
Uri.parse(isCN ? "https://gitee.com/wanghongenpin/proxypin/releases" : "$gitHub/releases")))
trailing: const Icon(Icons.open_in_new, size: 21),
onTap: () => _safeLaunch(
Uri.parse(isCN ? "https://gitee.com/wanghongenpin/proxypin/releases" : "$gitHub/releases"))),
ListTile(
dense: true,
title: Text(localizations.sponsorDonate),
subtitle: Text(localizations.sponsorSupport, style: const TextStyle(fontSize: 11)),
trailing: const Icon(Icons.favorite, color: Colors.redAccent, size: 21),
onTap: () => _showSponsorDialog(),
),
],
)),
);
}
Future<void> _safeLaunch(Uri uri) async {
await launchUrl(uri, mode: LaunchMode.externalApplication);
}
void _showSponsorDialog() {
bool isCN = Localizations.localeOf(context) == const Locale.fromSubtags(languageCode: 'zh');
List<Widget> sponsors = [
ListTile(
onTap: () => _safeLaunch(Uri.parse("https://afdian.com/a/proxypin")),
contentPadding: EdgeInsets.zero,
leading: const Icon(Icons.favorite, color: Colors.pinkAccent),
title: Text(localizations.sponsorAfdian),
)
];
final coffee = ListTile(
contentPadding: EdgeInsets.zero,
leading: const Icon(Icons.coffee, color: Colors.brown),
title: Text('Buy Me a Coffee'),
onTap: () => _safeLaunch(Uri.parse("https://buymeacoffee.com/proxypin")),
);
if (isCN) {
sponsors.add(coffee);
} else {
sponsors.insert(0, coffee);
}
showDialog(
context: context,
builder: (ctx) {
return AlertDialog(
title: Text(localizations.sponsorDonate),
contentPadding: const EdgeInsets.only(left: 20, top: 10, right: 20, bottom: 10),
content: SizedBox(
width: 340,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(localizations.sponsorThanks, style: const TextStyle(height: 1.4)),
const SizedBox(height: 16),
...sponsors
],
),
),
actions: [
TextButton(onPressed: () => Navigator.of(ctx).pop(), child: Text(localizations.close)),
],
);
},
);
}
}

View File

@@ -509,10 +509,14 @@ class IOSCertChecker {
return AlertDialog(
titlePadding: EdgeInsets.zero,
contentPadding: EdgeInsets.zero,
constraints: const BoxConstraints(maxHeight: 185),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
content: CertStatusCard(
installed: installed, trusted: trusted, margin: EdgeInsets.zero, proxyServer: ProxyServer.current!),
content: Container(
constraints: const BoxConstraints(maxHeight: 185),
child: CertStatusCard(
installed: installed,
trusted: trusted,
margin: EdgeInsets.zero,
proxyServer: ProxyServer.current!)),
actions: <Widget>[
TextButton(
onPressed: () {

View File

@@ -37,9 +37,10 @@ class _AboutState extends State<About> {
@override
Widget build(BuildContext context) {
AppLocalizations localizations = AppLocalizations.of(context)!;
bool isCN = Localizations.localeOf(context) == const Locale.fromSubtags(languageCode: 'zh');
String gitHub = "https://github.com/wanghongenpin/proxypin";
final String sponsorUrl = "https://github.com/sponsors/wanghongenpin";
return Scaffold(
appBar: AppBar(title: Text(localizations.about, style: const TextStyle(fontSize: 16)), centerTitle: true),
body: ListView(padding: const EdgeInsets.all(12), children: [
@@ -49,8 +50,7 @@ class _AboutState extends State<About> {
Center(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Text(isCN ? "全平台开源免费抓包软件" : "Full platform open source free capture HTTP(S) traffic software",
textAlign: TextAlign.center))),
child: Text(localizations.proxyPinSoftware, textAlign: TextAlign.center))),
const SizedBox(height: 8),
Center(child: Text("${localizations.version} ${AppConfiguration.version}")),
const SizedBox(height: 12),
@@ -65,14 +65,14 @@ class _AboutState extends State<About> {
title: const Text("GitHub"),
trailing: const Icon(Icons.open_in_new, size: 22),
onTap: () {
launchUrl(Uri.parse(gitHub), mode: LaunchMode.externalApplication);
_safeLaunch(Uri.parse(gitHub));
}),
Divider(height: 0, thickness: 0.4, color: Theme.of(context).dividerColor.withValues(alpha: 0.22)),
ListTile(
title: Text(localizations.feedback),
trailing: const Icon(Icons.open_in_new, size: 22),
onTap: () {
launchUrl(Uri.parse("$gitHub/issues"), mode: LaunchMode.externalApplication);
_safeLaunch(Uri.parse("$gitHub/issues"));
}),
Divider(height: 0, thickness: 0.4, color: Theme.of(context).dividerColor.withValues(alpha: 0.22)),
ListTile(
@@ -88,15 +88,71 @@ class _AboutState extends State<About> {
}),
Divider(height: 0, thickness: 0.4, color: Theme.of(context).dividerColor.withValues(alpha: 0.22)),
ListTile(
title: Text(isCN ? "下载地址" : "Download"),
title: Text(localizations.download),
trailing: const Icon(Icons.open_in_new, size: 22),
onTap: () {
final url = isCN
? "https://gitee.com/wanghongenpin/proxypin/releases"
: "$gitHub/releases";
launchUrl(Uri.parse(url), mode: LaunchMode.externalApplication);
final url = "$gitHub/releases";
_safeLaunch(Uri.parse(url));
}),
Divider(height: 0, thickness: 0.4, color: Theme.of(context).dividerColor.withValues(alpha: 0.22)),
// Sponsor / Donate entry
ListTile(
title: Text(localizations.sponsorDonate),
subtitle: Text(localizations.sponsorSupport, style: const TextStyle(fontSize: 12)),
trailing: const Icon(Icons.favorite, color: Colors.redAccent, size: 22),
onTap: () => _showSponsorDialog(localizations, sponsorUrl),
),
]))
]));
}
Future<void> _safeLaunch(Uri uri) async {
await launchUrl(uri, mode: LaunchMode.externalApplication);
}
void _showSponsorDialog(AppLocalizations l10n, String sponsorUrl) {
bool isCN = Localizations.localeOf(context) == const Locale.fromSubtags(languageCode: 'zh');
List<Widget> sponsors = [
ListTile(
onTap: () => _safeLaunch(Uri.parse("https://afdian.com/a/proxypin")),
contentPadding: EdgeInsets.zero,
leading: const Icon(Icons.favorite, color: Colors.pinkAccent),
title: Text(l10n.sponsorAfdian),
)
];
final coffee = ListTile(
contentPadding: EdgeInsets.zero,
leading: const Icon(Icons.coffee, color: Colors.brown),
title: Text('Buy Me a Coffee'),
onTap: () => _safeLaunch(Uri.parse("https://buymeacoffee.com/proxypin")),
);
if (isCN) {
sponsors.add(coffee);
} else {
sponsors.insert(0, coffee);
}
showDialog(
context: context,
builder: (ctx) {
return AlertDialog(
title: Text(l10n.sponsorDonate),
contentPadding: const EdgeInsets.only(left: 20, top: 10, right: 20, bottom: 10),
content: SizedBox(
width: 340,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [Text(l10n.sponsorThanks), const SizedBox(height: 12), ...sponsors],
),
),
actions: [
TextButton(onPressed: () => Navigator.of(ctx).pop(), child: Text(l10n.close)),
],
);
},
);
}
}