feat: refine AI navigation and accessibility recovery
This commit is contained in:
@@ -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('前往系统设置'),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user