feat(settings): Extensions tab — "watch this space" notice (T-456)
Built-in extensions are always on and there's no third-party install path yet, so the Extensions tab is a notice rather than a toggle list — a toggle list would let users brick the app by disabling load-bearing builtins. It explains that installing/enabling/disabling arrives with third-party (Lua) extensions and points at the records that pick it up (D-16 / T-8). Fleshes out the builtin.extensions-ui stub via the custom-control hatch. Adds two renderer guards — empty section/field labels render no chrome — so a notice-only category shows just its card. Tests: contributes the Extensions category + notice control; the notice renders. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1 +1,2 @@
|
||||
export 'src/extension.dart';
|
||||
export 'src/extensions_notice.dart';
|
||||
|
||||
@@ -1,17 +1,39 @@
|
||||
import 'package:clide/builtin/extensions_ui/src/extensions_notice.dart';
|
||||
import 'package:clide/extension/extension.dart';
|
||||
import 'package:clide/kernel/kernel.dart';
|
||||
|
||||
/// Tier-0 stub. Real implementation lands in a later tier; the extension
|
||||
/// is registered so the extensions-ui surface can list it as "installed,
|
||||
/// not yet implemented" and its id is reserved.
|
||||
/// Extensions settings tab (T-456). Built-in extensions are always on and there
|
||||
/// is no third-party install path yet, so the tab is a "watch this space"
|
||||
/// notice pointing at the records that track extension management (D-16 / T-8)
|
||||
/// rather than a toggle list. The real enable/install UI lands with third-party
|
||||
/// (Lua) extensions.
|
||||
class ExtensionsUiExtension extends ClideExtension {
|
||||
@override
|
||||
String get id => 'builtin.extensions-ui';
|
||||
@override
|
||||
String get title => 'Extensions UI';
|
||||
@override
|
||||
String get version => '0.0.0-stub';
|
||||
String get version => '0.1.0';
|
||||
@override
|
||||
List<String> get dependsOn => const [];
|
||||
|
||||
@override
|
||||
List<ContributionPoint> get contributions => const [];
|
||||
List<ContributionPoint> get contributions => [
|
||||
SettingsControlContribution(id: 'extensions-ui.notice-control', customId: 'extensions.notice', builder: (_) => const ExtensionsNotice()),
|
||||
const SettingsCategoryContribution(
|
||||
id: 'extensions',
|
||||
category: SettingsCategory(
|
||||
id: 'extensions',
|
||||
title: 'Extensions',
|
||||
iconName: 'puzzle-piece',
|
||||
priority: 80,
|
||||
sections: [
|
||||
SettingsSection(
|
||||
label: '',
|
||||
fields: [SettingsField(key: 'app.extensions._notice', kind: SettingsFieldKind.custom, label: '', customId: 'extensions.notice')],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
import 'package:clide/kernel/kernel.dart';
|
||||
import 'package:clide/widgets/widgets.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
/// The Extensions settings tab's "watch this space" notice (T-456).
|
||||
///
|
||||
/// Built-in extensions are always on and there's no third-party install path
|
||||
/// yet, so there's nothing to manage. Rather than ship a toggle list that could
|
||||
/// brick the app, the tab explains that extension management arrives with
|
||||
/// third-party (Lua) extensions and points at the records that track it.
|
||||
/// Rendered inside the section card (no own surface) via the custom-control
|
||||
/// registry.
|
||||
class ExtensionsNotice extends StatelessWidget {
|
||||
const ExtensionsNotice({super.key});
|
||||
|
||||
static const ns = 'builtin.extensions-ui';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final tokens = ClideTheme.of(context).surface;
|
||||
final i = ClideKernel.of(context).i18n;
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
ClideIcon(PhosphorIcons.byName('puzzle-piece'), size: 18, color: tokens.globalTextMuted),
|
||||
const SizedBox(width: 8),
|
||||
ClideText(
|
||||
i.string('notice.title', namespace: ns, placeholder: 'Extension management is coming'),
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
ClideText(
|
||||
i.string(
|
||||
'notice.body',
|
||||
namespace: ns,
|
||||
placeholder:
|
||||
'Installing, enabling, and disabling extensions arrives with third-party (Lua) extension support. For now the built-in extensions are always on.',
|
||||
),
|
||||
color: tokens.globalTextMuted,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
ClideText(
|
||||
i.string('notice.tracked', namespace: ns, placeholder: 'Tracked in T-8 (Tier 6) · D-16'),
|
||||
color: tokens.globalTextMuted,
|
||||
fontSize: clideFontCaption,
|
||||
fontFamily: clideMonoFamily,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -125,10 +125,11 @@ class _SectionCard extends StatelessWidget {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 2, bottom: 6),
|
||||
child: ClideText(section.label.toUpperCase(), fontSize: clideFontCaption, color: tokens.sidebarSectionHeader, fontFamily: clideMonoFamily),
|
||||
),
|
||||
if (section.label.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 2, bottom: 6),
|
||||
child: ClideText(section.label.toUpperCase(), fontSize: clideFontCaption, color: tokens.sidebarSectionHeader, fontFamily: clideMonoFamily),
|
||||
),
|
||||
ClideSurface(
|
||||
// Card surface (surface.md): panelHeader resolves to the `surface`
|
||||
// palette key (the elevated card tone); inputs inside recede to
|
||||
@@ -181,8 +182,7 @@ class _FieldRow extends StatelessWidget {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
label,
|
||||
const SizedBox(height: 10),
|
||||
if (field.label.isNotEmpty) ...[label, const SizedBox(height: 10)],
|
||||
builder?.call(context) ?? const SizedBox.shrink(),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"notice.title": { "translation": "Extension management is coming" },
|
||||
"notice.body": { "translation": "Installing, enabling, and disabling extensions arrives with third-party (Lua) extension support. For now the built-in extensions are always on." },
|
||||
"notice.tracked": { "translation": "Tracked in T-8 (Tier 6) · D-16" }
|
||||
}
|
||||
Reference in New Issue
Block a user