refactor: Update quick actions description and enhance AppCustomizationPage layout

- Revised the quick actions description in multiple languages to clarify their purpose as "Quickpills in chat."
- Adjusted the layout of AppCustomizationPage by reintroducing the quick pills section for improved user interaction.
- Modified spacing between UI elements for better visual consistency and usability.
- Streamlined the component structure to enhance maintainability and readability.
This commit is contained in:
cogwheel0
2025-10-19 16:06:20 +05:30
parent 89f897e8ad
commit 42efbe8fc5
16 changed files with 392 additions and 81 deletions

View File

@@ -59,8 +59,9 @@ class AppCustomizationPage extends ConsumerWidget {
themeMode,
themeDescription,
activeTheme,
settings,
),
const SizedBox(height: Spacing.xl),
const SizedBox(height: Spacing.md),
_buildLanguageSection(
context,
ref,
@@ -68,8 +69,6 @@ class AppCustomizationPage extends ConsumerWidget {
languageLabel,
),
const SizedBox(height: Spacing.xl),
_buildQuickPillsSection(context, ref, settings),
const SizedBox(height: Spacing.xl),
_buildTtsDropdownSection(context, ref, settings),
const SizedBox(height: Spacing.xl),
_buildChatSection(context, ref, settings),
@@ -118,6 +117,7 @@ class AppCustomizationPage extends ConsumerWidget {
ThemeMode themeMode,
String themeDescription,
TweakcnThemeDefinition activeTheme,
AppSettings settings,
) {
final theme = context.conduitTheme;
@@ -185,6 +185,8 @@ class AppCustomizationPage extends ConsumerWidget {
),
const SizedBox(height: Spacing.md),
_buildPaletteSelector(context, ref, activeTheme),
const SizedBox(height: Spacing.md),
_buildQuickPillsSection(context, ref, settings),
],
);
}
@@ -281,7 +283,6 @@ class AppCustomizationPage extends ConsumerWidget {
WidgetRef ref,
AppSettings settings,
) {
final theme = context.conduitTheme;
final selectedRaw = ref.watch(
appSettingsProvider.select((s) => s.quickPills),
);
@@ -333,66 +334,54 @@ class AppCustomizationPage extends ConsumerWidget {
? 'No actions'
: '$selectedCount action${selectedCount == 1 ? '' : 's'} selected';
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
l10n.onboardQuickTitle,
style:
theme.headingSmall?.copyWith(color: theme.sidebarForeground) ??
TextStyle(color: theme.sidebarForeground, fontSize: 18),
),
const SizedBox(height: Spacing.sm),
_ExpandableCard(
title: l10n.quickActionsDescription,
subtitle: selectedCountText,
icon: UiUtils.platformIcon(
ios: CupertinoIcons.bolt,
android: Icons.flash_on,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (selected.isNotEmpty)
Padding(
padding: const EdgeInsets.only(bottom: Spacing.md),
child: Align(
alignment: Alignment.centerRight,
child: TextButton(
onPressed: () => ref
.read(appSettingsProvider.notifier)
.setQuickPills(const []),
child: Text(l10n.clear),
),
),
return _ExpandableCard(
title: l10n.quickActionsDescription,
subtitle: selectedCountText,
icon: UiUtils.platformIcon(
ios: CupertinoIcons.bolt,
android: Icons.flash_on,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (selected.isNotEmpty)
Padding(
padding: const EdgeInsets.only(bottom: Spacing.md),
child: Align(
alignment: Alignment.centerRight,
child: TextButton(
onPressed: () => ref
.read(appSettingsProvider.notifier)
.setQuickPills(const []),
child: Text(l10n.clear),
),
Wrap(
spacing: Spacing.sm,
runSpacing: Spacing.sm,
children: [
ConduitChip(
label: l10n.web,
icon: Platform.isIOS ? CupertinoIcons.search : Icons.search,
isSelected: selected.contains('web'),
onTap: (selectedCount < 2 || selected.contains('web'))
? () => toggle('web')
: null,
),
ConduitChip(
label: l10n.imageGen,
icon: Platform.isIOS ? CupertinoIcons.photo : Icons.image,
isSelected: selected.contains('image'),
onTap: (selectedCount < 2 || selected.contains('image'))
? () => toggle('image')
: null,
),
...buildToolChips(),
],
),
),
Wrap(
spacing: Spacing.sm,
runSpacing: Spacing.sm,
children: [
ConduitChip(
label: l10n.web,
icon: Platform.isIOS ? CupertinoIcons.search : Icons.search,
isSelected: selected.contains('web'),
onTap: (selectedCount < 2 || selected.contains('web'))
? () => toggle('web')
: null,
),
ConduitChip(
label: l10n.imageGen,
icon: Platform.isIOS ? CupertinoIcons.photo : Icons.image,
isSelected: selected.contains('image'),
onTap: (selectedCount < 2 || selected.contains('image'))
? () => toggle('image')
: null,
),
...buildToolChips(),
],
),
),
],
],
),
);
}

View File

@@ -312,7 +312,7 @@
,
"appCustomization": "Anpassung",
"appCustomizationSubtitle": "Design, Sprache, Stimme und Quick Pills",
"quickActionsDescription": "Wähle bis zu zwei Schnellzugriffe, die neben dem Eingabefeld angepinnt werden",
"quickActionsDescription": "Schnellzugriffe im Chat",
"chatSettings": "Chat",
"sendOnEnter": "Mit Enter senden",
"sendOnEnterDescription": "Enter sendet (Soft-Tastatur). Cmd/Ctrl+Enter ebenfalls verfügbar",

View File

@@ -640,7 +640,7 @@
"@appCustomization": {"description": "Title of the customization settings page."},
"appCustomizationSubtitle": "Theme, language, voice, and quickpills",
"@appCustomizationSubtitle": {"description": "Subtitle shown under App Customization tile and page header."},
"quickActionsDescription": "Pick up to two shortcuts to pin near the composer",
"quickActionsDescription": "Quickpills in chat",
"@quickActionsDescription": {"description": "Helper text explaining quick action pill selection in customization."},
"chatSettings": "Chat",
"@chatSettings": {"description": "Section header for chat-related customization options."},

View File

@@ -305,7 +305,7 @@
},
"appCustomization": "Personalización",
"appCustomizationSubtitle": "Tema, idioma, voz y quickpills",
"quickActionsDescription": "Elige hasta dos accesos directos para anclar cerca del compositor",
"quickActionsDescription": "Accesos directos en chat",
"chatSettings": "Conversación",
"sendOnEnter": "Enviar con Enter",
"sendOnEnterDescription": "Enter envía (teclado virtual). Cmd/Ctrl+Enter también disponible",

View File

@@ -312,7 +312,7 @@
,
"appCustomization": "Personnalisation",
"appCustomizationSubtitle": "Thème, langue, voix et quickpills",
"quickActionsDescription": "Choisissez jusqu'à deux raccourcis à épingler près du champ de saisie",
"quickActionsDescription": "Raccourcis dans le chat",
"chatSettings": "Discussion",
"sendOnEnter": "Envoyer avec Entrée",
"sendOnEnterDescription": "Entrée envoie (clavier logiciel). Cmd/Ctrl+Entrée aussi disponible",

View File

@@ -312,7 +312,7 @@
,
"appCustomization": "Personalizzazione",
"appCustomizationSubtitle": "Tema, lingua, voce e quickpills",
"quickActionsDescription": "Scegli fino a due scorciatoie da fissare vicino al campo di input",
"quickActionsDescription": "Scorciatoie nella chat",
"chatSettings": "Chat",
"sendOnEnter": "Invia con Invio",
"sendOnEnterDescription": "Invio invia (tastiera software). Cmd/Ctrl+Invio disponibile",

View File

@@ -1697,7 +1697,7 @@ abstract class AppLocalizations {
/// Helper text explaining quick action pill selection in customization.
///
/// In en, this message translates to:
/// **'Pick up to two shortcuts to pin near the composer'**
/// **'Quickpills in chat'**
String get quickActionsDescription;
/// Section header for chat-related customization options.

View File

@@ -882,8 +882,7 @@ class AppLocalizationsDe extends AppLocalizations {
'Design, Sprache, Stimme und Quick Pills';
@override
String get quickActionsDescription =>
'Wähle bis zu zwei Schnellzugriffe, die neben dem Eingabefeld angepinnt werden';
String get quickActionsDescription => 'Schnellzugriffe im Chat';
@override
String get chatSettings => 'Chat';

View File

@@ -875,8 +875,7 @@ class AppLocalizationsEn extends AppLocalizations {
'Theme, language, voice, and quickpills';
@override
String get quickActionsDescription =>
'Pick up to two shortcuts to pin near the composer';
String get quickActionsDescription => 'Quickpills in chat';
@override
String get chatSettings => 'Chat';

View File

@@ -889,8 +889,7 @@ class AppLocalizationsFr extends AppLocalizations {
String get appCustomizationSubtitle => 'Thème, langue, voix et quickpills';
@override
String get quickActionsDescription =>
'Choisissez jusqu\'à deux raccourcis à épingler près du champ de saisie';
String get quickActionsDescription => 'Raccourcis dans le chat';
@override
String get chatSettings => 'Discussion';

View File

@@ -878,8 +878,7 @@ class AppLocalizationsIt extends AppLocalizations {
String get appCustomizationSubtitle => 'Tema, lingua, voce e quickpills';
@override
String get quickActionsDescription =>
'Scegli fino a due scorciatoie da fissare vicino al campo di input';
String get quickActionsDescription => 'Scorciatoie nella chat';
@override
String get chatSettings => 'Chat';

View File

@@ -305,7 +305,7 @@
},
"appCustomization": "Aanpassing",
"appCustomizationSubtitle": "Thema, taal, stem en quickpills",
"quickActionsDescription": "Kies maximaal twee snelkoppelingen om vast te pinnen bij de composer",
"quickActionsDescription": "Snelkoppelingen in chat",
"chatSettings": "Chat",
"sendOnEnter": "Verzenden met Enter",
"sendOnEnterDescription": "Enter verzendt (softtoetsenbord). Cmd/Ctrl+Enter ook beschikbaar",

View File

@@ -305,7 +305,7 @@
},
"appCustomization": "Настройка",
"appCustomizationSubtitle": "Тема, язык, голос и quickpills",
"quickActionsDescription": "Выберите до двух ярлыков для закрепления рядом с полем ввода",
"quickActionsDescription": "Быстрые клавиши в чате",
"chatSettings": "Чат",
"sendOnEnter": "Отправка по Enter",
"sendOnEnterDescription": "Enter отправляет (программная клавиатура). Также доступно Cmd/Ctrl+Enter",

View File

@@ -305,7 +305,7 @@
},
"appCustomization": "自定义",
"appCustomizationSubtitle": "主题、语言、语音和 quickpills",
"quickActionsDescription": "选择最多两个快捷方式以固定在撰写器附近",
"quickActionsDescription": "聊天快捷方式",
"chatSettings": "对话",
"sendOnEnter": "回车发送",
"sendOnEnterDescription": "回车发送软键盘。Cmd/Ctrl+Enter 也可用",

View File

@@ -473,6 +473,302 @@ class TweakcnThemes {
],
);
// Catppuccin (from @catppuccin.css)
static final TweakcnThemeVariant _catppuccinLight = TweakcnThemeVariant(
background: const Color(0xFFEFF1F5),
foreground: const Color(0xFF4C4F69),
card: const Color(0xFFFFFFFF),
cardForeground: const Color(0xFF4C4F69),
popover: const Color(0xFFCCD0DA),
popoverForeground: const Color(0xFF4C4F69),
primary: const Color(0xFF8839EF),
primaryForeground: const Color(0xFFFFFFFF),
secondary: const Color(0xFFCCD0DA),
secondaryForeground: const Color(0xFF4C4F69),
muted: const Color(0xFFDCE0E8),
mutedForeground: const Color(0xFF6C6F85),
accent: const Color(0xFF04A5E5),
accentForeground: const Color(0xFFFFFFFF),
destructive: const Color(0xFFD20F39),
destructiveForeground: const Color(0xFFFFFFFF),
border: const Color(0xFFBCC0CC),
input: const Color(0xFFCCD0DA),
ring: const Color(0xFF8839EF),
sidebarBackground: const Color(0xFFE6E9EF),
sidebarForeground: const Color(0xFF4C4F69),
sidebarPrimary: const Color(0xFF8839EF),
sidebarPrimaryForeground: const Color(0xFFFFFFFF),
sidebarAccent: const Color(0xFFDCE0E8),
sidebarAccentForeground: const Color(0xFF4C4F69),
sidebarBorder: const Color(0xFFBCC0CC),
sidebarRing: const Color(0xFF8839EF),
success: const Color(0xFF40A02B), // chart-3
successForeground: const Color(0xFF4C4F69),
warning: const Color(0xFFFE640B), // chart-4
warningForeground: const Color(0xFF4C4F69),
info: const Color(0xFF04A5E5), // chart-2
infoForeground: const Color(0xFFFFFFFF),
radius: 6,
fontSans: const <String>[
'Montserrat',
'ui-sans-serif',
'system-ui',
'-apple-system',
'BlinkMacSystemFont',
'Segoe UI',
'Roboto',
'Helvetica Neue',
'Arial',
'Noto Sans',
'sans-serif',
'Apple Color Emoji',
'Segoe UI Emoji',
'Segoe UI Symbol',
'Noto Color Emoji',
],
fontSerif: const <String>[
'Georgia',
'ui-serif',
'Cambria',
'Times New Roman',
'Times',
'serif',
],
fontMono: const <String>[
'Fira Code',
'ui-monospace',
'SFMono-Regular',
'Menlo',
'Monaco',
'Consolas',
'Liberation Mono',
'Courier New',
'monospace',
],
);
static final TweakcnThemeVariant _catppuccinDark = TweakcnThemeVariant(
background: const Color(0xFF181825),
foreground: const Color(0xFFCDD6F4),
card: const Color(0xFF1E1E2E),
cardForeground: const Color(0xFFCDD6F4),
popover: const Color(0xFF45475A),
popoverForeground: const Color(0xFFCDD6F4),
primary: const Color(0xFFCBA6F7),
primaryForeground: const Color(0xFF1E1E2E),
secondary: const Color(0xFF585B70),
secondaryForeground: const Color(0xFFCDD6F4),
muted: const Color(0xFF292C3C),
mutedForeground: const Color(0xFFA6ADC8),
accent: const Color(0xFF89DCEB),
accentForeground: const Color(0xFF1E1E2E),
destructive: const Color(0xFFF38BA8),
destructiveForeground: const Color(0xFF1E1E2E),
border: const Color(0xFF313244),
input: const Color(0xFF313244),
ring: const Color(0xFFCBA6F7),
sidebarBackground: const Color(0xFF11111B),
sidebarForeground: const Color(0xFFCDD6F4),
sidebarPrimary: const Color(0xFFCBA6F7),
sidebarPrimaryForeground: const Color(0xFF1E1E2E),
sidebarAccent: const Color(0xFF292C3C),
sidebarAccentForeground: const Color(0xFFCDD6F4),
sidebarBorder: const Color(0xFF45475A),
sidebarRing: const Color(0xFFCBA6F7),
success: const Color(0xFFA6E3A1), // chart-3
successForeground: const Color(0xFF181825),
warning: const Color(0xFFFAB387), // chart-4
warningForeground: const Color(0xFF181825),
info: const Color(0xFF89DCEB), // chart-2
infoForeground: const Color(0xFF181825),
radius: 6,
fontSans: const <String>[
'Montserrat',
'ui-sans-serif',
'system-ui',
'-apple-system',
'BlinkMacSystemFont',
'Segoe UI',
'Roboto',
'Helvetica Neue',
'Arial',
'Noto Sans',
'sans-serif',
'Apple Color Emoji',
'Segoe UI Emoji',
'Segoe UI Symbol',
'Noto Color Emoji',
],
fontSerif: const <String>[
'Georgia',
'ui-serif',
'Cambria',
'Times New Roman',
'Times',
'serif',
],
fontMono: const <String>[
'Fira Code',
'ui-monospace',
'SFMono-Regular',
'Menlo',
'Monaco',
'Consolas',
'Liberation Mono',
'Courier New',
'monospace',
],
);
// Tangerine (from @tangerine.css)
static final TweakcnThemeVariant _tangerineLight = TweakcnThemeVariant(
background: const Color(0xFFE8EBED),
foreground: const Color(0xFF333333),
card: const Color(0xFFFFFFFF),
cardForeground: const Color(0xFF333333),
popover: const Color(0xFFFFFFFF),
popoverForeground: const Color(0xFF333333),
primary: const Color(0xFFE05D38),
primaryForeground: const Color(0xFFFFFFFF),
secondary: const Color(0xFFF3F4F6),
secondaryForeground: const Color(0xFF4B5563),
muted: const Color(0xFFF9FAFB),
mutedForeground: const Color(0xFF6B7280),
accent: const Color(0xFFD6E4F0),
accentForeground: const Color(0xFF1E3A8A),
destructive: const Color(0xFFEF4444),
destructiveForeground: const Color(0xFFFFFFFF),
border: const Color(0xFFDCDFE2),
input: const Color(0xFFF4F5F7),
ring: const Color(0xFFE05D38),
sidebarBackground: const Color(0xFFDDDFE2),
sidebarForeground: const Color(0xFF333333),
sidebarPrimary: const Color(0xFFE05D38),
sidebarPrimaryForeground: const Color(0xFFFFFFFF),
sidebarAccent: const Color(0xFFD6E4F0),
sidebarAccentForeground: const Color(0xFF1E3A8A),
sidebarBorder: const Color(0xFFE5E7EB),
sidebarRing: const Color(0xFFE05D38),
success: const Color(0xFF86A7C8),
successForeground: const Color(0xFF333333),
warning: const Color(0xFFEEA591),
warningForeground: const Color(0xFF333333),
info: const Color(0xFF334C82),
infoForeground: const Color(0xFFFFFFFF),
radius: 12,
fontSans: const <String>[
'Inter',
'ui-sans-serif',
'system-ui',
'-apple-system',
'BlinkMacSystemFont',
'Segoe UI',
'Roboto',
'Helvetica Neue',
'Arial',
'Noto Sans',
'sans-serif',
'Apple Color Emoji',
'Segoe UI Emoji',
'Segoe UI Symbol',
'Noto Color Emoji',
],
fontSerif: const <String>[
'Source Serif 4',
'ui-serif',
'Georgia',
'Cambria',
'Times New Roman',
'Times',
'serif',
],
fontMono: const <String>[
'JetBrains Mono',
'ui-monospace',
'SFMono-Regular',
'Menlo',
'Monaco',
'Consolas',
'Liberation Mono',
'Courier New',
'monospace',
],
);
static final TweakcnThemeVariant _tangerineDark = TweakcnThemeVariant(
background: const Color(0xFF1C2433),
foreground: const Color(0xFFE5E5E5),
card: const Color(0xFF2A3040),
cardForeground: const Color(0xFFE5E5E5),
popover: const Color(0xFF262B38),
popoverForeground: const Color(0xFFE5E5E5),
primary: const Color(0xFFE05D38),
primaryForeground: const Color(0xFFFFFFFF),
secondary: const Color(0xFF2A303E),
secondaryForeground: const Color(0xFFE5E5E5),
muted: const Color(0xFF2A303E),
mutedForeground: const Color(0xFFA3A3A3),
accent: const Color(0xFF2A3656),
accentForeground: const Color(0xFFBFDBFE),
destructive: const Color(0xFFEF4444),
destructiveForeground: const Color(0xFFFFFFFF),
border: const Color(0xFF3D4354),
input: const Color(0xFF3D4354),
ring: const Color(0xFFE05D38),
sidebarBackground: const Color(0xFF2A303F),
sidebarForeground: const Color(0xFFE5E5E5),
sidebarPrimary: const Color(0xFFE05D38),
sidebarPrimaryForeground: const Color(0xFFFFFFFF),
sidebarAccent: const Color(0xFF2A3656),
sidebarAccentForeground: const Color(0xFFBFDBFE),
sidebarBorder: const Color(0xFF3D4354),
sidebarRing: const Color(0xFFE05D38),
success: const Color(0xFF86A7C8),
successForeground: const Color(0xFF1C2433),
warning: const Color(0xFFE6A08F),
warningForeground: const Color(0xFF1C2433),
info: const Color(0xFF466494),
infoForeground: const Color(0xFF1C2433),
radius: 12,
fontSans: const <String>[
'Inter',
'ui-sans-serif',
'system-ui',
'-apple-system',
'BlinkMacSystemFont',
'Segoe UI',
'Roboto',
'Helvetica Neue',
'Arial',
'Noto Sans',
'sans-serif',
'Apple Color Emoji',
'Segoe UI Emoji',
'Segoe UI Symbol',
'Noto Color Emoji',
],
fontSerif: const <String>[
'Source Serif 4',
'ui-serif',
'Georgia',
'Cambria',
'Times New Roman',
'Times',
'serif',
],
fontMono: const <String>[
'JetBrains Mono',
'ui-monospace',
'SFMono-Regular',
'Menlo',
'Monaco',
'Consolas',
'Liberation Mono',
'Courier New',
'monospace',
],
);
static final TweakcnThemeDefinition claude = TweakcnThemeDefinition(
id: 'claude',
label: 'Claude',
@@ -512,7 +808,39 @@ class TweakcnThemes {
],
);
static List<TweakcnThemeDefinition> all = [conduit, claude, t3Chat];
static final TweakcnThemeDefinition catppuccin = TweakcnThemeDefinition(
id: 'catppuccin',
label: 'Catppuccin',
description: 'Soft pastel palette.',
light: _catppuccinLight,
dark: _catppuccinDark,
preview: const <Color>[
Color(0xFF8839EF), // primary
Color(0xFF04A5E5), // accent
Color(0xFFEFF1F5), // background
],
);
static final TweakcnThemeDefinition tangerine = TweakcnThemeDefinition(
id: 'tangerine',
label: 'Tangerine',
description: 'Warm orange-and-slate palette.',
light: _tangerineLight,
dark: _tangerineDark,
preview: const <Color>[
Color(0xFFE05D38), // primary
Color(0xFFD6E4F0), // accent
Color(0xFFE8EBED), // background
],
);
static List<TweakcnThemeDefinition> all = [
conduit,
claude,
t3Chat,
catppuccin,
tangerine,
];
static TweakcnThemeDefinition byId(String? id) {
return all.firstWhere((theme) => theme.id == id, orElse: () => conduit);

View File

@@ -63,9 +63,7 @@ Future<void> showConduitContextMenu({
title: Text(
action.label,
style: AppTypography.standard.copyWith(
color: action.destructive
? Colors.red
: theme.textPrimary,
color: action.destructive ? Colors.red : theme.textPrimary,
fontWeight: FontWeight.w500,
),
),