Fix web ACP endpoint input stability

This commit is contained in:
Haitao Pan 2026-04-04 13:58:06 +08:00
parent 148ef162ae
commit 38050c681d
2 changed files with 78 additions and 12 deletions

View File

@ -153,9 +153,9 @@ extension WebSettingsPageGatewayMixinInternal on WebSettingsPageStateInternal {
() => directMessageInternal = result.message,
);
},
child: Text(appText('测试连接', 'Test')),
child: Text(appText('测试连接', 'Test Connection')),
),
FilledButton.icon(
FilledButton(
onPressed: controller.aiGatewayBusy
? null
: () async {
@ -195,7 +195,7 @@ extension WebSettingsPageGatewayMixinInternal on WebSettingsPageStateInternal {
);
}
},
icon: controller.aiGatewayBusy
child: controller.aiGatewayBusy
? const SizedBox(
width: 14,
height: 14,
@ -203,8 +203,7 @@ extension WebSettingsPageGatewayMixinInternal on WebSettingsPageStateInternal {
strokeWidth: 2,
),
)
: const Icon(Icons.play_circle_outline_rounded),
label: Text(appText('保存并生效', 'Save & apply')),
: Text(appText('保存并生效', 'Save & apply')),
),
],
),
@ -263,6 +262,7 @@ extension WebSettingsPageGatewayMixinInternal on WebSettingsPageStateInternal {
const SizedBox(height: 16),
...controller.settingsDraft.externalAcpEndpoints.map(
(profile) => Padding(
key: ValueKey('web-external-acp-card-${profile.providerKey}'),
padding: const EdgeInsets.only(bottom: 12),
child: buildExternalAcpProviderCardInternal(
context,
@ -335,19 +335,21 @@ extension WebSettingsPageGatewayMixinInternal on WebSettingsPageStateInternal {
),
const SizedBox(height: 12),
TextField(
key: ValueKey('web-external-acp-label-${profile.providerKey}'),
controller: labelController,
decoration: InputDecoration(
labelText: appText('显示名称', 'Display name'),
),
onChanged: (_) => stageExternalAcpDraftInternal(controller),
onChanged: (_) => setStateInternal(() {}),
),
const SizedBox(height: 12),
TextField(
key: ValueKey('web-external-acp-endpoint-${profile.providerKey}'),
controller: endpointController,
decoration: InputDecoration(
labelText: appText('ACP Server Endpoint', 'ACP Server Endpoint'),
),
onChanged: (_) => stageExternalAcpDraftInternal(controller),
onChanged: (_) => setStateInternal(() {}),
),
const SizedBox(height: 8),
Text(
@ -652,9 +654,9 @@ extension WebSettingsPageGatewayMixinInternal on WebSettingsPageStateInternal {
'${result.state.toUpperCase()} · ${result.message}',
);
},
child: Text(appText('Test', 'Test')),
child: Text(appText('测试连接', 'Test Connection')),
),
FilledButton.icon(
FilledButton(
onPressed: controller.relayBusy
? null
: () async {
@ -686,14 +688,13 @@ extension WebSettingsPageGatewayMixinInternal on WebSettingsPageStateInternal {
onMessageChanged('$error');
}
},
icon: controller.relayBusy
child: controller.relayBusy
? const SizedBox(
width: 14,
height: 14,
child: CircularProgressIndicator(strokeWidth: 2),
)
: const Icon(Icons.play_circle_outline_rounded),
label: Text(appText('保存并生效', 'Save & apply')),
: Text(appText('保存并生效', 'Save & apply')),
),
],
),

View File

@ -0,0 +1,65 @@
@TestOn('vm')
library;
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:xworkmate/app/app_controller_web.dart' as web_app;
import 'package:xworkmate/models/app_models.dart';
import 'package:xworkmate/runtime/runtime_models.dart';
import 'package:xworkmate/web/web_settings_page_core.dart';
import '../test_support.dart';
void main() {
testWidgets('Web external ACP editor supports continuous input', (
WidgetTester tester,
) async {
SharedPreferences.setMockInitialValues(<String, Object>{});
final controller = web_app.AppController();
addTearDown(controller.dispose);
await tester.pump(const Duration(milliseconds: 100));
await tester.pumpAndSettle();
final customProfile = buildCustomExternalAcpEndpointProfile(
controller.settingsDraft.externalAcpEndpoints,
label: 'Initial Name',
endpoint: 'wss://initial.example.com/acp',
);
await controller.saveSettingsDraft(
controller.settingsDraft.copyWith(
externalAcpEndpoints: <ExternalAcpEndpointProfile>[
...controller.settingsDraft.externalAcpEndpoints,
customProfile,
],
),
);
controller.setSettingsTab(SettingsTab.gateway);
await pumpPage(
tester,
child: SizedBox(
width: 1280,
height: 960,
child: WebSettingsPage(controller: controller, showSectionTabs: false),
),
platform: TargetPlatform.macOS,
);
final labelField = find.byKey(
ValueKey('web-external-acp-label-${customProfile.providerKey}'),
);
expect(labelField, findsOneWidget);
expect(find.text('测试连接'), findsWidgets);
expect(find.text('保存并生效'), findsWidgets);
await tester.enterText(labelField, 'A');
await tester.pump();
await tester.enterText(labelField, 'AB');
await tester.pump();
await tester.enterText(labelField, 'ABC');
await tester.pump();
expect(find.text('ABC'), findsOneWidget);
});
}