fix: streamline gateway settings and mac packaging cleanup
This commit is contained in:
parent
0fb0ccdf17
commit
235d41c5fe
@ -1,4 +1,5 @@
|
||||
PODS:
|
||||
- CocoaAsyncSocket (7.6.5)
|
||||
- device_info_plus (0.0.1):
|
||||
- Flutter
|
||||
- file_selector_ios (0.0.1):
|
||||
@ -58,6 +59,10 @@ PODS:
|
||||
- nanopb/encode (3.30910.0)
|
||||
- package_info_plus (0.4.5):
|
||||
- Flutter
|
||||
- patrol (0.0.1):
|
||||
- CocoaAsyncSocket (~> 7.6)
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- PromisesObjC (2.4.0)
|
||||
- shared_preferences_foundation (0.0.1):
|
||||
- Flutter
|
||||
@ -73,11 +78,13 @@ DEPENDENCIES:
|
||||
- irondash_engine_context (from `.symlinks/plugins/irondash_engine_context/ios`)
|
||||
- mobile_scanner (from `.symlinks/plugins/mobile_scanner/ios`)
|
||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||
- patrol (from `.symlinks/plugins/patrol/darwin`)
|
||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- super_native_extensions (from `.symlinks/plugins/super_native_extensions/ios`)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- CocoaAsyncSocket
|
||||
- GoogleDataTransport
|
||||
- GoogleMLKit
|
||||
- GoogleToolboxForMac
|
||||
@ -105,12 +112,15 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/mobile_scanner/ios"
|
||||
package_info_plus:
|
||||
:path: ".symlinks/plugins/package_info_plus/ios"
|
||||
patrol:
|
||||
:path: ".symlinks/plugins/patrol/darwin"
|
||||
shared_preferences_foundation:
|
||||
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||
super_native_extensions:
|
||||
:path: ".symlinks/plugins/super_native_extensions/ios"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
|
||||
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
|
||||
file_selector_ios: ec57ec07954363dd730b642e765e58f199bb621a
|
||||
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||
@ -128,6 +138,7 @@ SPEC CHECKSUMS:
|
||||
mobile_scanner: af8f71879eaba2bbcb4d86c6a462c3c0e7f23036
|
||||
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
|
||||
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
|
||||
patrol: cea8074f183a2a4232d0ebd10569ae05149ada42
|
||||
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
||||
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
|
||||
super_native_extensions: b763c02dc3a8fd078389f410bf15149179020cb4
|
||||
|
||||
@ -37,13 +37,6 @@ extension SettingsPageGatewayMixinInternal on SettingsPageStateInternal {
|
||||
) {
|
||||
if (!widget.showSectionTabs) {
|
||||
return [
|
||||
buildGatewayOverviewCardInternal(
|
||||
context,
|
||||
controller,
|
||||
settings,
|
||||
uiFeatures,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
buildOnlineAccountCardInternal(context, controller, settings),
|
||||
const SizedBox(height: 16),
|
||||
buildAcpBridgeServerModeCardInternal(
|
||||
@ -95,13 +88,6 @@ extension SettingsPageGatewayMixinInternal on SettingsPageStateInternal {
|
||||
),
|
||||
};
|
||||
return [
|
||||
buildGatewayOverviewCardInternal(
|
||||
context,
|
||||
controller,
|
||||
settings,
|
||||
uiFeatures,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
SectionTabs(
|
||||
items: <String>[
|
||||
appText('用户登录状态', 'User Login State'),
|
||||
@ -145,10 +131,10 @@ extension SettingsPageGatewayMixinInternal on SettingsPageStateInternal {
|
||||
GatewayIntegrationSubTabInternal.llm => const <Widget>[],
|
||||
GatewayIntegrationSubTabInternal.acp => const <Widget>[],
|
||||
GatewayIntegrationSubTabInternal.skills => const <Widget>[],
|
||||
GatewayIntegrationSubTabInternal.advancedConfig =>
|
||||
uiFeatures.supportsGatewayAdvancedCustomMode
|
||||
? <Widget>[
|
||||
...buildGatewayAdvancedSectionsInternal(
|
||||
GatewayIntegrationSubTabInternal.advancedConfig =>
|
||||
uiFeatures.supportsGatewayAdvancedCustomMode
|
||||
? <Widget>[
|
||||
...buildGatewayAdvancedSectionsInternal(
|
||||
context,
|
||||
controller,
|
||||
settings,
|
||||
@ -160,85 +146,6 @@ extension SettingsPageGatewayMixinInternal on SettingsPageStateInternal {
|
||||
];
|
||||
}
|
||||
|
||||
Widget buildGatewayOverviewCardInternal(
|
||||
BuildContext context,
|
||||
AppController controller,
|
||||
SettingsSnapshot settings,
|
||||
UiFeatureAccess uiFeatures,
|
||||
) {
|
||||
final accountController = controller.settingsController;
|
||||
final modeConfig = settings.acpBridgeServerModeConfig;
|
||||
final supportsSelfHosted = uiFeatures.supportsGatewaySelfHostedBase;
|
||||
final supportsAdvancedOverrides =
|
||||
uiFeatures.supportsGatewayAdvancedCustomMode;
|
||||
final loginStatus = accountController.accountMfaRequired
|
||||
? appText('MFA 待验证', 'MFA pending')
|
||||
: accountController.accountBusy
|
||||
? appText('登录中', 'Signing in')
|
||||
: accountController.accountSignedIn
|
||||
? appText('已登录', 'Signed in')
|
||||
: appText('未登录', 'Signed out');
|
||||
final defaultSource = supportsSelfHosted && modeConfig.usesSelfHostedBase
|
||||
? appText('自建服务', 'Self-hosted')
|
||||
: appText('svc.plus 提供', 'svc.plus provided');
|
||||
final hasAdvancedOverrides =
|
||||
supportsAdvancedOverrides &&
|
||||
modeConfig.mode == AcpBridgeServerMode.advancedCustom;
|
||||
return SurfaceCard(
|
||||
key: const ValueKey('gateway-configuration-overview-card'),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
appText('最终生效配置概览', 'Effective Configuration Overview'),
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
supportsAdvancedOverrides
|
||||
? appText(
|
||||
'先确认登录状态,再确定默认连接来源,最后按需用高级自定义模式覆盖默认配置。',
|
||||
'Confirm login state first, choose the default connection source second, then apply advanced custom overrides only where needed.',
|
||||
)
|
||||
: appText(
|
||||
'先确认登录状态,再查看当前默认连接来源。',
|
||||
'Confirm login state first, then review the current default connection source.',
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Wrap(
|
||||
spacing: 12,
|
||||
runSpacing: 12,
|
||||
children: [
|
||||
StatusChipInternal(
|
||||
key: const ValueKey('gateway-overview-login-status'),
|
||||
label: '${appText('登录状态', 'Login')}: $loginStatus',
|
||||
tone: accountController.accountSignedIn
|
||||
? StatusChipToneInternal.ready
|
||||
: StatusChipToneInternal.idle,
|
||||
),
|
||||
StatusChipInternal(
|
||||
key: const ValueKey('gateway-overview-default-source'),
|
||||
label:
|
||||
'${appText('默认连接来源', 'Default Source')}: $defaultSource',
|
||||
tone: StatusChipToneInternal.ready,
|
||||
),
|
||||
if (supportsAdvancedOverrides)
|
||||
StatusChipInternal(
|
||||
key: const ValueKey('gateway-overview-advanced-override'),
|
||||
label:
|
||||
'${appText('高级覆盖', 'Advanced Override')}: ${hasAdvancedOverrides ? appText('已启用', 'Enabled') : appText('未启用', 'Disabled')}',
|
||||
tone: hasAdvancedOverrides
|
||||
? StatusChipToneInternal.ready
|
||||
: StatusChipToneInternal.idle,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> buildGatewayAdvancedSectionsInternal(
|
||||
BuildContext context,
|
||||
AppController controller,
|
||||
|
||||
@ -14,6 +14,32 @@ FLUTTER_BUILD_STATE_DIR="${ROOT_DIR}/.dart_tool/flutter_build"
|
||||
MACOS_BUILD_DIR="${ROOT_DIR}/build/macos"
|
||||
NATIVE_ASSETS_DIR="${ROOT_DIR}/build/native_assets"
|
||||
|
||||
remove_tree_with_retries() {
|
||||
local path="$1"
|
||||
local attempts="${2:-5}"
|
||||
local delay_seconds="${3:-1}"
|
||||
local try=1
|
||||
|
||||
[[ -e "$path" ]] || return 0
|
||||
|
||||
while (( try <= attempts )); do
|
||||
chmod -R u+w "$path" 2>/dev/null || true
|
||||
rm -rf "$path" 2>/dev/null || true
|
||||
|
||||
if [[ ! -e "$path" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if (( try == attempts )); then
|
||||
echo "Failed to remove generated path after ${attempts} attempts: $path" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
sleep "$delay_seconds"
|
||||
((try++))
|
||||
done
|
||||
}
|
||||
|
||||
if [[ ! -f "$PUBSPEC_PATH" ]]; then
|
||||
echo "Missing pubspec: $PUBSPEC_PATH" >&2
|
||||
exit 1
|
||||
@ -40,7 +66,9 @@ echo "Building $APP_NAME $APP_VERSION ($APP_BUILD) for macOS..."
|
||||
# Flutter caches native-asset installation state under .dart_tool/flutter_build,
|
||||
# but Xcode consumes the copied frameworks from build/native_assets/macos.
|
||||
# Reset both locations so packaging cannot reuse a stale stamp or stale layout.
|
||||
rm -rf "$FLUTTER_BUILD_STATE_DIR" "$MACOS_BUILD_DIR" "$NATIVE_ASSETS_DIR"
|
||||
remove_tree_with_retries "$FLUTTER_BUILD_STATE_DIR"
|
||||
remove_tree_with_retries "$MACOS_BUILD_DIR"
|
||||
remove_tree_with_retries "$NATIVE_ASSETS_DIR"
|
||||
|
||||
BUILD_ARGS=(
|
||||
flutter build macos
|
||||
|
||||
@ -234,15 +234,15 @@ void main() {
|
||||
|
||||
expect(
|
||||
find.byKey(const ValueKey('gateway-configuration-overview-card')),
|
||||
findsOneWidget,
|
||||
findsNothing,
|
||||
);
|
||||
expect(
|
||||
find.byKey(const ValueKey('gateway-overview-login-status')),
|
||||
findsOneWidget,
|
||||
findsNothing,
|
||||
);
|
||||
expect(
|
||||
find.byKey(const ValueKey('gateway-overview-default-source')),
|
||||
findsOneWidget,
|
||||
findsNothing,
|
||||
);
|
||||
expect(
|
||||
find.byKey(const ValueKey('gateway-overview-advanced-override')),
|
||||
@ -415,7 +415,7 @@ void main() {
|
||||
expect(find.byKey(const ValueKey('account-base-url-field')), findsOneWidget);
|
||||
expect(find.byKey(const ValueKey('account-username-field')), findsOneWidget);
|
||||
expect(find.byKey(const ValueKey('account-password-field')), findsOneWidget);
|
||||
expect(find.byKey(const ValueKey('acp-bridge-mode-cloud')), findsNothing);
|
||||
expect(find.byKey(const ValueKey('acp-bridge-mode-cloud')), findsOneWidget);
|
||||
expect(
|
||||
find.byKey(const ValueKey('acp-bridge-mode-self-hosted')),
|
||||
findsNothing,
|
||||
@ -437,9 +437,6 @@ void main() {
|
||||
|
||||
await _pumpSettingsPage(tester, controller, tab: SettingsTab.gateway);
|
||||
|
||||
await tester.tap(find.byKey(const ValueKey('section-tab-高级自定义模式')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('Vault Server'), findsAtLeastNWidgets(1));
|
||||
expect(find.text('VAULT_SERVER_URL'), findsOneWidget);
|
||||
expect(
|
||||
@ -460,9 +457,6 @@ void main() {
|
||||
|
||||
await _pumpSettingsPage(tester, controller, tab: SettingsTab.gateway);
|
||||
|
||||
await tester.tap(find.byKey(const ValueKey('section-tab-高级自定义模式')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('外部 ACP Server Endpoint'), findsOneWidget);
|
||||
expect(find.textContaining('Codex'), findsWidgets);
|
||||
expect(find.textContaining('OpenCode'), findsWidgets);
|
||||
@ -496,9 +490,6 @@ void main() {
|
||||
|
||||
await _pumpSettingsPage(tester, controller, tab: SettingsTab.gateway);
|
||||
|
||||
await tester.tap(find.byKey(const ValueKey('section-tab-高级自定义模式')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await _ensureVisible(
|
||||
tester,
|
||||
find.byKey(const ValueKey('external-acp-provider-add-button')),
|
||||
@ -536,9 +527,6 @@ void main() {
|
||||
|
||||
await _pumpSettingsPage(tester, controller, tab: SettingsTab.gateway);
|
||||
|
||||
await tester.tap(find.byKey(const ValueKey('section-tab-高级自定义模式')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('~/.agents/skills'), findsOneWidget);
|
||||
expect(find.text('/Users/tester/.agents/skills'), findsOneWidget);
|
||||
expect(find.text('~/.codex/skills'), findsOneWidget);
|
||||
@ -569,8 +557,6 @@ void main() {
|
||||
);
|
||||
|
||||
await _pumpSettingsPage(tester, controller, tab: SettingsTab.gateway);
|
||||
await tester.tap(find.byKey(const ValueKey('section-tab-高级自定义模式')));
|
||||
await tester.pumpAndSettle();
|
||||
await _ensureVisible(
|
||||
tester,
|
||||
find.byKey(const ValueKey('skill-directory-batch-add-button')),
|
||||
@ -629,8 +615,6 @@ paths:
|
||||
);
|
||||
|
||||
await _pumpSettingsPage(tester, controller, tab: SettingsTab.gateway);
|
||||
await tester.tap(find.byKey(const ValueKey('section-tab-高级自定义模式')));
|
||||
await tester.pumpAndSettle();
|
||||
await _ensureVisible(
|
||||
tester,
|
||||
find.byKey(const ValueKey('skill-directory-batch-add-button')),
|
||||
@ -672,8 +656,6 @@ paths:
|
||||
);
|
||||
|
||||
await _pumpSettingsPage(tester, controller, tab: SettingsTab.gateway);
|
||||
await tester.tap(find.byKey(const ValueKey('section-tab-高级自定义模式')));
|
||||
await tester.pumpAndSettle();
|
||||
await _ensureVisible(
|
||||
tester,
|
||||
find.byKey(const ValueKey('skill-directory-batch-add-button')),
|
||||
@ -712,11 +694,14 @@ paths:
|
||||
testWidgets('SettingsPage gateway sections can collapse individually', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
final controller = await createTestController(tester);
|
||||
final controller = await createTestController(
|
||||
tester,
|
||||
uiFeatureManifest: _gatewayAdvancedManifestInternal(),
|
||||
);
|
||||
|
||||
await _pumpSettingsPage(tester, controller, tab: SettingsTab.gateway);
|
||||
|
||||
await tester.tap(find.byTooltip('折叠').first);
|
||||
await tester.tap(find.text('OpenClaw Gateway').first);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byKey(const ValueKey('gateway-host-field')), findsNothing);
|
||||
@ -726,7 +711,7 @@ paths:
|
||||
findsNothing,
|
||||
);
|
||||
|
||||
await tester.tap(find.byTooltip('展开').first);
|
||||
await tester.tap(find.text('OpenClaw Gateway').first);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byKey(const ValueKey('gateway-host-field')), findsOneWidget);
|
||||
@ -746,8 +731,6 @@ paths:
|
||||
);
|
||||
|
||||
await _pumpSettingsPage(tester, controller, tab: SettingsTab.gateway);
|
||||
await tester.tap(find.byKey(const ValueKey('section-tab-高级自定义模式')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await _ensureVisible(tester, find.text('外部 ACP Server Endpoint'));
|
||||
await tester.tap(find.text('外部 ACP Server Endpoint').first);
|
||||
@ -791,8 +774,6 @@ paths:
|
||||
);
|
||||
|
||||
await _pumpSettingsPage(tester, controller, tab: SettingsTab.gateway);
|
||||
await tester.tap(find.byKey(const ValueKey('section-tab-高级自定义模式')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final labelField = find.byKey(
|
||||
ValueKey('external-acp-label-${customProfile.providerKey}'),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user