feat: refine AI navigation and accessibility recovery

This commit is contained in:
2026-08-26 22:58:26 +08:00
parent c6f98b5445
commit 9ccbdfead4
15 changed files with 521 additions and 203 deletions
@@ -264,13 +264,6 @@ class _MePageState extends State<MePage> {
'预算管理',
onTap: () => context.push('/budget'),
),
_row(
AppIcons.avatarAsset(PublicConfigApi.companionAvatarKey),
context.jz.aiBackground,
AppTheme.ai,
session.aiEnabled ? 'AI 报告' : '报告',
onTap: () => context.push('/report'),
),
_row(
AppIcons.tag,
context.jz.primaryBackground,
@@ -32,7 +32,7 @@ class _ScreenshotSettingsPageState extends State<ScreenshotSettingsPage>
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
_check();
_check(waitForConnection: true);
_diagnosticRefreshTimer = Timer.periodic(
const Duration(seconds: 2),
(_) => _refreshRunningDiagnostic(),
@@ -67,9 +67,11 @@ class _ScreenshotSettingsPageState extends State<ScreenshotSettingsPage>
_check().whenComplete(() => _diagnosticRefreshInFlight = false);
}
Future<void> _check() async {
Future<void> _check({bool waitForConnection = false}) async {
try {
var status = await ScreenshotChannel.recognitionStatus();
var status = waitForConnection
? await ScreenshotChannel.waitForAccessibilityConnection()
: await ScreenshotChannel.recognitionStatus();
final invalid = <String>[
if (status.accessibilityEvents &&
(!status.accessibilityAuthorized ||
@@ -180,7 +182,7 @@ class _ScreenshotSettingsPageState extends State<ScreenshotSettingsPage>
Future<void> _resumeAuthorization() async {
if (_authorizing) return;
await _check();
await _check(waitForConnection: true);
final key = _pendingAuthorizationKey;
final status = _status;
if (key == null || status == null) return;
@@ -431,7 +433,13 @@ class _ScreenshotSettingsPageState extends State<ScreenshotSettingsPage>
'仅在微信和支付宝疑似支付流程中读取可见文字,并按需在内存中进行本地截图 OCR;不保存图片、完整控件树,也不监听按键。',
authorized: status!.accessibilityAuthorized,
connected: status.accessibilityConnected,
statusLabel: status.accessibilityConnectionLabel,
onOpenSettings: ScreenshotChannel.openAccessibilitySettings,
onRetry:
status.accessibilityAuthorized &&
!status.accessibilityConnected
? () => _check(waitForConnection: true)
: null,
child: Column(
children: [
JzSwitchTile(
@@ -888,7 +896,7 @@ class _BackgroundKeepAliveCard extends StatelessWidget {
),
const SizedBox(height: 10),
Text(
'无障碍和通知监听由 Android 独立轻量进程运行。请允许记之后台活动,'
'无障碍和通知监听由 Android 系统持续绑定。请允许记之后台活动,'
'${isVivo ? '并在 OriginOS 中开启自启动,' : ''}'
'否则系统清理进程后可能暂时收不到支付事件。',
style: TextStyle(
@@ -932,6 +940,7 @@ class _RecognitionCard extends StatelessWidget {
final String? statusLabel;
final Widget child;
final VoidCallback? onOpenSettings;
final VoidCallback? onRetry;
const _RecognitionCard({
required this.icon,
@@ -942,6 +951,7 @@ class _RecognitionCard extends StatelessWidget {
required this.child,
this.statusLabel,
this.onOpenSettings,
this.onRetry,
});
@override
@@ -1012,42 +1022,25 @@ class _RecognitionCard extends StatelessWidget {
),
const SizedBox(height: 6),
child,
if (onOpenSettings != null) ...[
if (onOpenSettings != null || onRetry != null) ...[
const SizedBox(height: 6),
Align(
alignment: Alignment.centerLeft,
child: Semantics(
button: true,
label: '打开系统权限设置',
child: InkWell(
onTap: onOpenSettings,
borderRadius: BorderRadius.circular(10),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 4,
vertical: 8,
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.settings_outlined,
size: 17,
color: AppTheme.primary,
),
const SizedBox(width: 6),
Text(
'系统权限设置',
style: TextStyle(
color: AppTheme.primary,
fontWeight: FontWeight.w700,
),
),
],
),
Wrap(
spacing: 6,
runSpacing: 4,
children: [
if (onRetry != null)
TextButton.icon(
onPressed: onRetry,
icon: const Icon(Icons.refresh_rounded, size: 18),
label: const Text('重新检测'),
),
),
),
if (onOpenSettings != null)
TextButton.icon(
onPressed: onOpenSettings,
icon: const Icon(Icons.settings_outlined, size: 18),
label: const Text('前往系统设置'),
),
],
),
],
],