feat: add web search availability provider and enhance feature toggles in chat and tools modal

This commit is contained in:
cogwheel0
2025-08-24 20:55:51 +05:30
parent cc46799e20
commit 4cd00e9193
5 changed files with 77 additions and 47 deletions

View File

@@ -657,8 +657,10 @@ Future<void> _sendMessageInternal(
}
}
// Check feature toggles for API
final webSearchEnabled = ref.read(webSearchEnabledProvider);
// Check feature toggles for API (gated by server availability)
final webSearchEnabled =
ref.read(webSearchEnabledProvider) &&
ref.read(webSearchAvailableProvider);
final imageGenerationEnabled = ref.read(imageGenerationEnabledProvider);
// Prepare tools list - pass tool IDs directly

View File

@@ -65,7 +65,12 @@ class _EnhancedImageAttachmentState
parent: _animationController,
curve: Curves.easeInOut,
);
_loadImage();
// Defer loading until after first frame to avoid accessing inherited widgets
// (e.g., Localizations) during initState
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!mounted) return;
_loadImage();
});
}
@override

View File

@@ -382,14 +382,13 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
)!.addAttachment,
),
const SizedBox(width: Spacing.sm),
// Quick pills: wrap in horizontal scroller to prevent overflow
// Quick pills: no scroll, clip text within fixed max width
Expanded(
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
physics: const BouncingScrollPhysics(),
child: Row(
children: [
_buildPillButton(
child: Row(
children: [
Flexible(
fit: FlexFit.loose,
child: _buildPillButton(
icon: Platform.isIOS
? CupertinoIcons.search
: Icons.search,
@@ -409,9 +408,12 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
}
: null,
),
if (imageGenAvailable) ...[
const SizedBox(width: Spacing.sm),
_buildPillButton(
),
if (imageGenAvailable) ...[
const SizedBox(width: Spacing.sm),
Flexible(
fit: FlexFit.loose,
child: _buildPillButton(
icon: Platform.isIOS
? CupertinoIcons.photo
: Icons.image,
@@ -431,9 +433,9 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
}
: null,
),
],
),
],
),
],
),
),
const SizedBox(width: Spacing.sm),
@@ -705,20 +707,25 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
alignment: Alignment.center,
padding: const EdgeInsets.symmetric(horizontal: Spacing.md),
decoration: BoxDecoration(
color: isActive
? context.conduitTheme.buttonPrimary
: context.conduitTheme.cardBackground,
// Align with unified tools modal: keep subtle card background even when active
color: context.conduitTheme.cardBackground,
borderRadius: BorderRadius.circular(AppBorderRadius.xl),
// Reduce perceived height variance: only show shadow when active
boxShadow: isActive ? ConduitShadows.button : null,
// No elevation to match modal chips
boxShadow: null,
),
child: Center(
child: Text(
label,
style: AppTypography.labelStyle.copyWith(
color: isActive
? context.conduitTheme.buttonPrimaryText
: context.conduitTheme.textPrimary,
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 140),
child: Text(
label,
maxLines: 1,
overflow: TextOverflow.ellipsis,
softWrap: false,
style: AppTypography.labelStyle.copyWith(
color: isActive
? context.conduitTheme.buttonPrimary
: context.conduitTheme.textPrimary,
),
),
),
),

View File

@@ -25,6 +25,7 @@ class _UnifiedToolsModalState extends ConsumerState<UnifiedToolsModal> {
final webSearchEnabled = ref.watch(webSearchEnabledProvider);
final imageGenEnabled = ref.watch(imageGenerationEnabledProvider);
final imageGenAvailable = ref.watch(imageGenerationAvailableProvider);
final webSearchAvailable = ref.watch(webSearchAvailableProvider);
final selectedToolIds = ref.watch(selectedToolIdsProvider);
final toolsAsync = ref.watch(toolsListProvider);
@@ -59,21 +60,22 @@ class _UnifiedToolsModalState extends ConsumerState<UnifiedToolsModal> {
// Full tiles for Web and Image features
Column(
children: [
_buildFeatureTile(
title: AppLocalizations.of(context)!.webSearch,
description: AppLocalizations.of(
context,
)!.webSearchDescription,
icon: Platform.isIOS
? CupertinoIcons.search
: Icons.search,
isActive: webSearchEnabled,
onTap: () {
HapticFeedback.lightImpact();
ref.read(webSearchEnabledProvider.notifier).state =
!webSearchEnabled;
},
),
if (webSearchAvailable)
_buildFeatureTile(
title: AppLocalizations.of(context)!.webSearch,
description: AppLocalizations.of(
context,
)!.webSearchDescription,
icon: Platform.isIOS
? CupertinoIcons.search
: Icons.search,
isActive: webSearchEnabled,
onTap: () {
HapticFeedback.lightImpact();
ref.read(webSearchEnabledProvider.notifier).state =
!webSearchEnabled;
},
),
if (imageGenAvailable)
_buildFeatureTile(
title: AppLocalizations.of(context)!.imageGeneration,