feat: align workspace ready actions and naming
This commit is contained in:
parent
27fd3a3286
commit
a8cce8e32c
@ -99,7 +99,7 @@ class _SettingsAccountPanelState extends State<SettingsAccountPanel>
|
||||
controller: _signedOutTabController,
|
||||
tabs: [
|
||||
Tab(text: appText('svc.plus 云端同步', 'svc.plus Cloud Sync')),
|
||||
Tab(text: appText('手动 Bridge 配置', 'Manual Bridge Config')),
|
||||
Tab(text: appText('AI 智能体工作空间', 'AI Agentic Workspace')),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
@ -189,15 +189,15 @@ class _ManualBridgePanel extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
appText('手动 Bridge 配置', 'Manual Bridge Config'),
|
||||
appText('AI 智能体工作空间', 'AI Agentic Workspace'),
|
||||
style: theme.textTheme.headlineMedium,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
appText(
|
||||
'直接配置本地或私有 xworkmate-bridge 地址与令牌。',
|
||||
'Configure local or private xworkmate-bridge address and token directly.',
|
||||
'直接配置本地或私有 AI 智能体工作空间地址与令牌。',
|
||||
'Configure a local or private AI Agentic Workspace address and token directly.',
|
||||
),
|
||||
style: theme.textTheme.titleMedium?.copyWith(
|
||||
color: theme.textTheme.bodyMedium?.color?.withValues(
|
||||
@ -799,7 +799,7 @@ String _connectionSourceLabel(
|
||||
);
|
||||
return mode == _SignedInAccountMode.accountSync
|
||||
? appText('svc.plus 托管配置', 'svc.plus managed profile')
|
||||
: appText('手动 Bridge 配置', 'Manual Bridge configuration');
|
||||
: appText('AI 智能体工作空间', 'AI Agentic Workspace');
|
||||
}
|
||||
|
||||
class _TokenConfiguredSummary extends StatelessWidget {
|
||||
|
||||
@ -82,27 +82,34 @@ class WorkspaceManagementResult extends StatelessWidget {
|
||||
label: Text(WorkspaceManagementText.copyAddress),
|
||||
),
|
||||
OutlinedButton.icon(
|
||||
onPressed: () => Clipboard.setData(ClipboardData(text: token)),
|
||||
onPressed: () =>
|
||||
Clipboard.setData(ClipboardData(text: token)),
|
||||
icon: const Icon(Icons.key_outlined),
|
||||
label: Text(appText('复制 Token', 'Copy token')),
|
||||
),
|
||||
OutlinedButton.icon(
|
||||
onPressed: result == null
|
||||
? null
|
||||
: () => _saveAsDefault(result),
|
||||
icon: const Icon(Icons.bookmark_add_outlined),
|
||||
label: Text(appText('设为默认', 'Set as default')),
|
||||
),
|
||||
OutlinedButton.icon(
|
||||
onPressed: result == null ? null : () => _downloadResult(result),
|
||||
: () => _downloadResult(result),
|
||||
icon: const Icon(Icons.download_outlined),
|
||||
label: Text(appText('下载凭据', 'Download credentials')),
|
||||
),
|
||||
FilledButton.tonalIcon(
|
||||
onPressed: null,
|
||||
FilledButton.icon(
|
||||
onPressed: result == null
|
||||
? null
|
||||
: () => _openWorkspace(result),
|
||||
icon: const Icon(Icons.settings_remote_outlined),
|
||||
label: Text(WorkspaceManagementText.connectToWorkspace),
|
||||
),
|
||||
FilledButton.icon(
|
||||
onPressed: result == null
|
||||
? null
|
||||
: () => _saveAsDefault(result),
|
||||
icon: const Icon(Icons.bookmark_add_outlined),
|
||||
label: Text(
|
||||
appText('设为默认保存配置', 'Set as default and save config'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
@ -121,17 +128,41 @@ class WorkspaceManagementResult extends StatelessWidget {
|
||||
await File(location.path).writeAsString(result.downloadText);
|
||||
}
|
||||
|
||||
Future<void> _openWorkspace(WorkspaceDeploymentResult result) async {
|
||||
final url = result.url.trim();
|
||||
if (url.isEmpty) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (Platform.isMacOS) {
|
||||
await Process.run('open', [url]);
|
||||
return;
|
||||
}
|
||||
if (Platform.isWindows) {
|
||||
await Process.run('cmd', ['/c', 'start', '', url]);
|
||||
return;
|
||||
}
|
||||
if (Platform.isLinux) {
|
||||
await Process.run('xdg-open', [url]);
|
||||
}
|
||||
} catch (error) {
|
||||
debugPrint('Open workspace URL failed: $error');
|
||||
await Clipboard.setData(ClipboardData(text: url));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _saveAsDefault(WorkspaceDeploymentResult result) async {
|
||||
final settingsController = appController.settingsController;
|
||||
final currentSettings = appController.settings;
|
||||
final nextSettings = await settingsController.buildSavedAccountProfileSettings(
|
||||
settings: currentSettings,
|
||||
accountBaseUrl: currentSettings.accountBaseUrl,
|
||||
accountIdentifier: currentSettings.accountUsername,
|
||||
bridgeServerUrl: result.url,
|
||||
bridgeToken: result.bridgeToken,
|
||||
isManualBridge: true,
|
||||
);
|
||||
final nextSettings = await settingsController
|
||||
.buildSavedAccountProfileSettings(
|
||||
settings: currentSettings,
|
||||
accountBaseUrl: currentSettings.accountBaseUrl,
|
||||
accountIdentifier: currentSettings.accountUsername,
|
||||
bridgeServerUrl: result.url,
|
||||
bridgeToken: result.bridgeToken,
|
||||
isManualBridge: true,
|
||||
);
|
||||
await appController.saveSettings(nextSettings, refreshAfterSave: true);
|
||||
}
|
||||
|
||||
@ -143,7 +174,9 @@ class WorkspaceManagementResult extends StatelessWidget {
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.errorContainer.withValues(alpha: 0.45),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: theme.colorScheme.error.withValues(alpha: 0.35)),
|
||||
border: Border.all(
|
||||
color: theme.colorScheme.error.withValues(alpha: 0.35),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@ -162,8 +195,7 @@ class WorkspaceManagementResult extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
controller.errorMessage ??
|
||||
appText('请查看日志。', 'Check logs.'),
|
||||
controller.errorMessage ?? appText('请查看日志。', 'Check logs.'),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@ -156,7 +156,7 @@ void main() {
|
||||
),
|
||||
);
|
||||
|
||||
await tester.tap(find.text('手动 Bridge 配置'));
|
||||
await tester.tap(find.text('AI 智能体工作空间'));
|
||||
await tester.pump();
|
||||
await tester.enterText(
|
||||
find.byKey(const ValueKey('settings-manual-bridge-url-field')),
|
||||
@ -211,7 +211,7 @@ void main() {
|
||||
),
|
||||
);
|
||||
|
||||
await tester.tap(find.text('手动 Bridge 配置'));
|
||||
await tester.tap(find.text('AI 智能体工作空间'));
|
||||
await tester.pump();
|
||||
|
||||
expect(saveCount, 0);
|
||||
@ -265,7 +265,7 @@ void main() {
|
||||
),
|
||||
);
|
||||
|
||||
await tester.tap(find.text('手动 Bridge 配置'));
|
||||
await tester.tap(find.text('AI 智能体工作空间'));
|
||||
await tester.pump();
|
||||
await tester.enterText(
|
||||
find.byKey(const ValueKey('settings-manual-bridge-url-field')),
|
||||
|
||||
@ -34,7 +34,10 @@ void main() {
|
||||
|
||||
expect(find.text('创建 / 升级 AI 工作空间'), findsOneWidget);
|
||||
expect(find.text('workspace.example.com'), findsOneWidget);
|
||||
expect(find.byKey(const Key('workspace-management-upgrade-button')), findsOneWidget);
|
||||
expect(
|
||||
find.byKey(const Key('workspace-management-upgrade-button')),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(
|
||||
tester
|
||||
.widget<FilledButton>(
|
||||
@ -77,7 +80,10 @@ void main() {
|
||||
provisionController.updateForm(logsExpanded: true);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byKey(const Key('workspace-management-log-content')), findsOneWidget);
|
||||
expect(
|
||||
find.byKey(const Key('workspace-management-log-content')),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(find.textContaining('hello log'), findsOneWidget);
|
||||
});
|
||||
|
||||
@ -108,9 +114,13 @@ void main() {
|
||||
expect(find.text('https://xworkmate-bridge.example.com'), findsOneWidget);
|
||||
expect(find.text('bridge-token-123'), findsOneWidget);
|
||||
expect(find.text('下载凭据'), findsOneWidget);
|
||||
expect(find.text('连接到该工作空间'), findsOneWidget);
|
||||
expect(find.text('设为默认保存配置'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('success result can save deployed bridge as default', (tester) async {
|
||||
testWidgets('success result can save deployed bridge as default', (
|
||||
tester,
|
||||
) async {
|
||||
final store = _MemorySecureConfigStore();
|
||||
final appController = _NoopAppController(store: store);
|
||||
final provisionController = WorkspaceProvisionController(
|
||||
@ -140,8 +150,8 @@ void main() {
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.ensureVisible(find.text('设为默认'));
|
||||
await tester.tap(find.text('设为默认'));
|
||||
await tester.ensureVisible(find.text('设为默认保存配置'));
|
||||
await tester.tap(find.text('设为默认保存配置'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(
|
||||
@ -150,11 +160,7 @@ void main() {
|
||||
);
|
||||
expect(
|
||||
await appController.settingsController.loadSecretValueByRef(
|
||||
appController
|
||||
.settings
|
||||
.acpBridgeServerModeConfig
|
||||
.selfHosted
|
||||
.passwordRef,
|
||||
appController.settings.acpBridgeServerModeConfig.selfHosted.passwordRef,
|
||||
),
|
||||
'save-token-123',
|
||||
);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user