chore(release): bump to v0.6.2 and gate account access
This commit is contained in:
parent
144428f054
commit
47273a2d41
@ -134,6 +134,12 @@ mobile:
|
||||
build_modes: [debug, profile, release]
|
||||
description: Mobile settings gateway tab
|
||||
ui_surface: settings_page
|
||||
account_access:
|
||||
enabled: false
|
||||
release_tier: experimental
|
||||
build_modes: [debug, profile, release]
|
||||
description: Mobile account access section
|
||||
ui_surface: settings_page
|
||||
vault_server:
|
||||
enabled: false
|
||||
release_tier: experimental
|
||||
@ -319,6 +325,12 @@ desktop:
|
||||
build_modes: [debug, profile, release]
|
||||
description: Desktop settings gateway tab
|
||||
ui_surface: settings_page
|
||||
account_access:
|
||||
enabled: false
|
||||
release_tier: experimental
|
||||
build_modes: [debug, profile, release]
|
||||
description: Desktop account access section
|
||||
ui_surface: settings_page
|
||||
vault_server:
|
||||
enabled: false
|
||||
release_tier: experimental
|
||||
@ -444,6 +456,12 @@ web:
|
||||
build_modes: [debug, profile, release]
|
||||
description: Web settings gateway tab
|
||||
ui_surface: web_settings_page
|
||||
account_access:
|
||||
enabled: false
|
||||
release_tier: experimental
|
||||
build_modes: []
|
||||
description: Web does not expose account access section
|
||||
ui_surface: web_settings_page
|
||||
vault_server:
|
||||
enabled: false
|
||||
release_tier: experimental
|
||||
|
||||
@ -65,6 +65,7 @@ abstract final class UiFeatureKeys {
|
||||
static const settingsGeneral = 'settings.general';
|
||||
static const settingsWorkspace = 'settings.workspace';
|
||||
static const settingsGateway = 'settings.gateway';
|
||||
static const settingsAccountAccess = 'settings.account_access';
|
||||
static const settingsVaultServer = 'settings.vault_server';
|
||||
static const settingsGatewaySetupCode = 'settings.gateway_setup_code';
|
||||
static const settingsAgents = 'settings.agents';
|
||||
@ -256,6 +257,12 @@ mobile:
|
||||
build_modes: [debug, profile, release]
|
||||
description: Mobile settings gateway tab
|
||||
ui_surface: settings_page
|
||||
account_access:
|
||||
enabled: false
|
||||
release_tier: experimental
|
||||
build_modes: [debug, profile, release]
|
||||
description: Mobile account access section
|
||||
ui_surface: settings_page
|
||||
vault_server:
|
||||
enabled: false
|
||||
release_tier: experimental
|
||||
@ -441,6 +448,12 @@ desktop:
|
||||
build_modes: [debug, profile, release]
|
||||
description: Desktop settings gateway tab
|
||||
ui_surface: settings_page
|
||||
account_access:
|
||||
enabled: false
|
||||
release_tier: experimental
|
||||
build_modes: [debug, profile, release]
|
||||
description: Desktop account access section
|
||||
ui_surface: settings_page
|
||||
vault_server:
|
||||
enabled: false
|
||||
release_tier: experimental
|
||||
@ -566,6 +579,12 @@ web:
|
||||
build_modes: [debug, profile, release]
|
||||
description: Web settings gateway tab
|
||||
ui_surface: web_settings_page
|
||||
account_access:
|
||||
enabled: false
|
||||
release_tier: experimental
|
||||
build_modes: []
|
||||
description: Web does not expose account access section
|
||||
ui_surface: web_settings_page
|
||||
vault_server:
|
||||
enabled: false
|
||||
release_tier: experimental
|
||||
@ -948,6 +967,9 @@ class UiFeatureAccess {
|
||||
bool get supportsDiagnostics =>
|
||||
isEnabledPath(UiFeatureKeys.settingsDiagnostics);
|
||||
|
||||
bool get supportsAccountAccess =>
|
||||
isEnabledPath(UiFeatureKeys.settingsAccountAccess);
|
||||
|
||||
bool get supportsGatewaySetupCode =>
|
||||
isEnabledPath(UiFeatureKeys.settingsGatewaySetupCode);
|
||||
|
||||
|
||||
@ -240,7 +240,12 @@ class _SettingsPageState extends State<SettingsPage> {
|
||||
}
|
||||
|
||||
return switch (_tab) {
|
||||
SettingsTab.general => _buildGeneral(context, controller, settings),
|
||||
SettingsTab.general => _buildGeneral(
|
||||
context,
|
||||
controller,
|
||||
settings,
|
||||
uiFeatures,
|
||||
),
|
||||
SettingsTab.workspace => _buildWorkspace(context, controller, settings),
|
||||
SettingsTab.gateway => _buildGateway(
|
||||
context,
|
||||
@ -458,6 +463,7 @@ class _SettingsPageState extends State<SettingsPage> {
|
||||
BuildContext context,
|
||||
AppController controller,
|
||||
SettingsSnapshot settings,
|
||||
UiFeatureAccess uiFeatures,
|
||||
) {
|
||||
return [
|
||||
SurfaceCard(
|
||||
@ -492,55 +498,57 @@ class _SettingsPageState extends State<SettingsPage> {
|
||||
settings.copyWith(showDockIcon: value),
|
||||
),
|
||||
),
|
||||
_SwitchRow(
|
||||
label: appText('账号本地模式', 'Account local mode'),
|
||||
value: settings.accountLocalMode,
|
||||
onChanged: (value) => _saveSettings(
|
||||
controller,
|
||||
settings.copyWith(accountLocalMode: value),
|
||||
if (uiFeatures.supportsAccountAccess)
|
||||
_SwitchRow(
|
||||
label: appText('账号本地模式', 'Account local mode'),
|
||||
value: settings.accountLocalMode,
|
||||
onChanged: (value) => _saveSettings(
|
||||
controller,
|
||||
settings.copyWith(accountLocalMode: value),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (controller.supportsDesktopIntegration)
|
||||
_buildLinuxDesktopIntegration(context, controller, settings),
|
||||
SurfaceCard(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
appText('账号访问', 'Account Access'),
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_EditableField(
|
||||
label: appText('账号服务地址', 'Account Base URL'),
|
||||
value: settings.accountBaseUrl,
|
||||
onSubmitted: (value) => _saveSettings(
|
||||
controller,
|
||||
settings.copyWith(accountBaseUrl: value),
|
||||
if (uiFeatures.supportsAccountAccess)
|
||||
SurfaceCard(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
appText('账号访问', 'Account Access'),
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
),
|
||||
_EditableField(
|
||||
label: appText('账号用户名', 'Account Username'),
|
||||
value: settings.accountUsername,
|
||||
onSubmitted: (value) => _saveSettings(
|
||||
controller,
|
||||
settings.copyWith(accountUsername: value),
|
||||
const SizedBox(height: 16),
|
||||
_EditableField(
|
||||
label: appText('账号服务地址', 'Account Base URL'),
|
||||
value: settings.accountBaseUrl,
|
||||
onSubmitted: (value) => _saveSettings(
|
||||
controller,
|
||||
settings.copyWith(accountBaseUrl: value),
|
||||
),
|
||||
),
|
||||
),
|
||||
_EditableField(
|
||||
label: appText('工作区名称', 'Workspace Label'),
|
||||
value: settings.accountWorkspace,
|
||||
onSubmitted: (value) => _saveSettings(
|
||||
controller,
|
||||
settings.copyWith(accountWorkspace: value),
|
||||
_EditableField(
|
||||
label: appText('账号用户名', 'Account Username'),
|
||||
value: settings.accountUsername,
|
||||
onSubmitted: (value) => _saveSettings(
|
||||
controller,
|
||||
settings.copyWith(accountUsername: value),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
_EditableField(
|
||||
label: appText('工作区名称', 'Workspace Label'),
|
||||
value: settings.accountWorkspace,
|
||||
onSubmitted: (value) => _saveSettings(
|
||||
controller,
|
||||
settings.copyWith(accountWorkspace: value),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ name: xworkmate
|
||||
description: "XWorkmate desktop-first AI workspace shell."
|
||||
publish_to: 'none'
|
||||
|
||||
version: 0.6.1+1
|
||||
version: 0.6.2+1
|
||||
build-date: 2026-03-20
|
||||
build-id: 4183a40
|
||||
|
||||
|
||||
@ -91,6 +91,48 @@ void main() {
|
||||
expect(controller.themeMode, ThemeMode.light);
|
||||
});
|
||||
|
||||
testWidgets('SettingsPage hides account access controls by default', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
final controller = await createTestController(tester);
|
||||
|
||||
await pumpPage(
|
||||
tester,
|
||||
child: SettingsPage(controller: controller),
|
||||
platform: TargetPlatform.macOS,
|
||||
);
|
||||
|
||||
expect(find.text('账号访问'), findsNothing);
|
||||
expect(find.text('Account Access'), findsNothing);
|
||||
expect(find.text('账号本地模式'), findsNothing);
|
||||
expect(find.text('Account local mode'), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('SettingsPage can expose account access when feature enabled', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
final manifest = UiFeatureManifest.fallback().copyWithFeature(
|
||||
platform: UiFeaturePlatform.desktop,
|
||||
module: 'settings',
|
||||
feature: 'account_access',
|
||||
enabled: true,
|
||||
releaseTier: UiFeatureReleaseTier.experimental,
|
||||
);
|
||||
final controller = await createTestController(
|
||||
tester,
|
||||
uiFeatureManifest: manifest,
|
||||
);
|
||||
|
||||
await pumpPage(
|
||||
tester,
|
||||
child: SettingsPage(controller: controller),
|
||||
platform: TargetPlatform.macOS,
|
||||
);
|
||||
|
||||
expect(find.text('账号访问'), findsOneWidget);
|
||||
expect(find.text('账号本地模式'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('SettingsPage integration tab exposes unified gateway controls', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
|
||||
@ -236,7 +236,7 @@ void main() {
|
||||
final controller = AppController(desktopPlatformService: service);
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
await Future<void>.delayed(const Duration(milliseconds: 50));
|
||||
await _waitFor(() => !controller.initializing);
|
||||
|
||||
expect(controller.supportsDesktopIntegration, isTrue);
|
||||
expect(
|
||||
@ -276,7 +276,7 @@ void main() {
|
||||
addTearDown(server.close);
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
await Future<void>.delayed(const Duration(milliseconds: 50));
|
||||
await _waitFor(() => !controller.initializing);
|
||||
|
||||
final result = await controller.testGatewayConnectionDraft(
|
||||
profile: GatewayConnectionProfile.defaults().copyWith(
|
||||
@ -296,3 +296,16 @@ void main() {
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _waitFor(
|
||||
bool Function() condition, {
|
||||
Duration timeout = const Duration(seconds: 2),
|
||||
}) async {
|
||||
final stopwatch = Stopwatch()..start();
|
||||
while (!condition()) {
|
||||
if (stopwatch.elapsed > timeout) {
|
||||
fail('Condition not met within ${timeout.inMilliseconds}ms');
|
||||
}
|
||||
await Future<void>.delayed(const Duration(milliseconds: 10));
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user