refactor: enhance localization support in chat and voice input features
- Integrated localization for various dialog messages and UI elements in the chat and voice input components. - Updated the confirmation dialog to utilize localized strings for delete messages, improving user experience across different languages. - Enhanced voice input sheet to reflect localized text for status updates, action buttons, and prompts, ensuring consistency in user interactions. - Improved the file attachment widget to display the attachment label in a localized manner, enhancing accessibility for users in different regions. - Streamlined localization management by centralizing string retrieval, promoting maintainability and clarity in the codebase.
This commit is contained in:
@@ -1673,11 +1673,13 @@ class _ChatPageState extends ConsumerState<ChatPage> {
|
|||||||
final selectedMessages = _getSelectedMessages();
|
final selectedMessages = _getSelectedMessages();
|
||||||
if (selectedMessages.isEmpty) return;
|
if (selectedMessages.isEmpty) return;
|
||||||
|
|
||||||
|
final l10n = AppLocalizations.of(context)!;
|
||||||
ThemedDialogs.confirm(
|
ThemedDialogs.confirm(
|
||||||
context,
|
context,
|
||||||
title: 'Delete Messages',
|
title: l10n.deleteMessagesTitle,
|
||||||
message: 'Delete ${selectedMessages.length} messages?',
|
message: l10n.deleteMessagesMessage(selectedMessages.length),
|
||||||
confirmText: 'Delete',
|
confirmText: l10n.delete,
|
||||||
|
cancelText: l10n.cancel,
|
||||||
isDestructive: true,
|
isDestructive: true,
|
||||||
).then((confirmed) async {
|
).then((confirmed) async {
|
||||||
if (confirmed == true) {
|
if (confirmed == true) {
|
||||||
@@ -2285,6 +2287,7 @@ class _VoiceInputSheetState extends ConsumerState<_VoiceInputSheet> {
|
|||||||
context: context,
|
context: context,
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
|
final l10n = AppLocalizations.of(context)!;
|
||||||
return Container(
|
return Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: context.conduitTheme.surfaceBackground,
|
color: context.conduitTheme.surfaceBackground,
|
||||||
@@ -2306,7 +2309,7 @@ class _VoiceInputSheetState extends ConsumerState<_VoiceInputSheet> {
|
|||||||
const SheetHandle(),
|
const SheetHandle(),
|
||||||
const SizedBox(height: Spacing.md),
|
const SizedBox(height: Spacing.md),
|
||||||
Text(
|
Text(
|
||||||
'Select Language',
|
l10n.selectLanguage,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: AppTypography.headlineSmall,
|
fontSize: AppTypography.headlineSmall,
|
||||||
color: context.conduitTheme.textPrimary,
|
color: context.conduitTheme.textPrimary,
|
||||||
@@ -2395,6 +2398,12 @@ class _VoiceInputSheetState extends ConsumerState<_VoiceInputSheet> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final media = MediaQuery.of(context);
|
final media = MediaQuery.of(context);
|
||||||
final isCompact = media.size.height < 680;
|
final isCompact = media.size.height < 680;
|
||||||
|
final l10n = AppLocalizations.of(context)!;
|
||||||
|
final statusText = _isListening
|
||||||
|
? (_voiceService.hasLocalStt
|
||||||
|
? l10n.voiceStatusListening
|
||||||
|
: l10n.voiceStatusRecording)
|
||||||
|
: l10n.voice;
|
||||||
return Container(
|
return Container(
|
||||||
height: media.size.height * (isCompact ? 0.45 : 0.6),
|
height: media.size.height * (isCompact ? 0.45 : 0.6),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
@@ -2425,11 +2434,7 @@ class _VoiceInputSheetState extends ConsumerState<_VoiceInputSheet> {
|
|||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
_isListening
|
statusText,
|
||||||
? (_voiceService.hasLocalStt
|
|
||||||
? 'Listening…'
|
|
||||||
: 'Recording…')
|
|
||||||
: 'Voice',
|
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: AppTypography.headlineMedium,
|
fontSize: AppTypography.headlineMedium,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
@@ -2532,7 +2537,7 @@ class _VoiceInputSheetState extends ConsumerState<_VoiceInputSheet> {
|
|||||||
),
|
),
|
||||||
const SizedBox(width: Spacing.xs),
|
const SizedBox(width: Spacing.xs),
|
||||||
Text(
|
Text(
|
||||||
'Hold to talk',
|
l10n.voiceHoldToTalk,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: context.conduitTheme.textSecondary,
|
color: context.conduitTheme.textSecondary,
|
||||||
),
|
),
|
||||||
@@ -2555,7 +2560,7 @@ class _VoiceInputSheetState extends ConsumerState<_VoiceInputSheet> {
|
|||||||
),
|
),
|
||||||
const SizedBox(width: Spacing.xs),
|
const SizedBox(width: Spacing.xs),
|
||||||
Text(
|
Text(
|
||||||
'Auto-send',
|
l10n.voiceAutoSend,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: context.conduitTheme.textSecondary,
|
color: context.conduitTheme.textSecondary,
|
||||||
),
|
),
|
||||||
@@ -2729,7 +2734,7 @@ class _VoiceInputSheetState extends ConsumerState<_VoiceInputSheet> {
|
|||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'Transcript',
|
l10n.voiceTranscript,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: AppTypography.labelSmall,
|
fontSize: AppTypography.labelSmall,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
@@ -2762,9 +2767,9 @@ class _VoiceInputSheetState extends ConsumerState<_VoiceInputSheet> {
|
|||||||
_recognizedText.isEmpty
|
_recognizedText.isEmpty
|
||||||
? (_isListening
|
? (_isListening
|
||||||
? (_voiceService.hasLocalStt
|
? (_voiceService.hasLocalStt
|
||||||
? 'Speak now…'
|
? l10n.voicePromptSpeakNow
|
||||||
: 'Recording…')
|
: l10n.voiceStatusRecording)
|
||||||
: 'Tap Start to begin')
|
: l10n.voicePromptTapStart)
|
||||||
: _recognizedText,
|
: _recognizedText,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: isUltra
|
fontSize: isUltra
|
||||||
@@ -2825,7 +2830,9 @@ class _VoiceInputSheetState extends ConsumerState<_VoiceInputSheet> {
|
|||||||
if (showStartStop) ...[
|
if (showStartStop) ...[
|
||||||
Expanded(
|
Expanded(
|
||||||
child: ConduitButton(
|
child: ConduitButton(
|
||||||
text: _isListening ? 'Stop' : 'Start',
|
text: _isListening
|
||||||
|
? l10n.voiceActionStop
|
||||||
|
: l10n.voiceActionStart,
|
||||||
isSecondary: true,
|
isSecondary: true,
|
||||||
isCompact: isCompact,
|
isCompact: isCompact,
|
||||||
onPressed: _isListening
|
onPressed: _isListening
|
||||||
@@ -2839,7 +2846,7 @@ class _VoiceInputSheetState extends ConsumerState<_VoiceInputSheet> {
|
|||||||
if (showSend) ...[
|
if (showSend) ...[
|
||||||
Expanded(
|
Expanded(
|
||||||
child: ConduitButton(
|
child: ConduitButton(
|
||||||
text: 'Send',
|
text: l10n.send,
|
||||||
isCompact: isCompact,
|
isCompact: isCompact,
|
||||||
onPressed: _recognizedText.isNotEmpty
|
onPressed: _recognizedText.isNotEmpty
|
||||||
? _sendText
|
? _sendText
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ class MessageAttachmentPreview extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(width: Spacing.xs),
|
const SizedBox(width: Spacing.xs),
|
||||||
Text(
|
Text(
|
||||||
'Attachment',
|
AppLocalizations.of(context)!.attachmentLabel,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: context.conduitTheme.textPrimary.withValues(
|
color: context.conduitTheme.textPrimary.withValues(
|
||||||
alpha: 0.8,
|
alpha: 0.8,
|
||||||
|
|||||||
@@ -460,11 +460,12 @@ class AppCustomizationPage extends ConsumerWidget {
|
|||||||
AppSettings settings,
|
AppSettings settings,
|
||||||
) {
|
) {
|
||||||
final theme = context.conduitTheme;
|
final theme = context.conduitTheme;
|
||||||
|
final l10n = AppLocalizations.of(context)!;
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'Chat',
|
l10n.chatSettings,
|
||||||
style:
|
style:
|
||||||
theme.headingSmall?.copyWith(color: theme.textPrimary) ??
|
theme.headingSmall?.copyWith(color: theme.textPrimary) ??
|
||||||
TextStyle(color: theme.textPrimary, fontSize: 18),
|
TextStyle(color: theme.textPrimary, fontSize: 18),
|
||||||
@@ -476,9 +477,8 @@ class AppCustomizationPage extends ConsumerWidget {
|
|||||||
Platform.isIOS ? CupertinoIcons.paperplane : Icons.keyboard_return,
|
Platform.isIOS ? CupertinoIcons.paperplane : Icons.keyboard_return,
|
||||||
color: theme.buttonPrimary,
|
color: theme.buttonPrimary,
|
||||||
),
|
),
|
||||||
title: 'Send on Enter',
|
title: l10n.sendOnEnter,
|
||||||
subtitle:
|
subtitle: l10n.sendOnEnterDescription,
|
||||||
'Enter sends (soft keyboard). Cmd/Ctrl+Enter also available',
|
|
||||||
trailing: Switch.adaptive(
|
trailing: Switch.adaptive(
|
||||||
value: settings.sendOnEnter,
|
value: settings.sendOnEnter,
|
||||||
onChanged: (value) =>
|
onChanged: (value) =>
|
||||||
|
|||||||
@@ -127,12 +127,24 @@
|
|||||||
"onboardQuickBullet2": "Neuer Chat starten oder Modelle oben verwalten"
|
"onboardQuickBullet2": "Neuer Chat starten oder Modelle oben verwalten"
|
||||||
,
|
,
|
||||||
"addAttachment": "Anhang hinzufügen",
|
"addAttachment": "Anhang hinzufügen",
|
||||||
|
"attachmentLabel": "Anhang",
|
||||||
"tools": "Werkzeuge",
|
"tools": "Werkzeuge",
|
||||||
"voiceInput": "Spracheingabe",
|
"voiceInput": "Spracheingabe",
|
||||||
|
"voice": "Sprache",
|
||||||
|
"voiceStatusListening": "Hört zu…",
|
||||||
|
"voiceStatusRecording": "Nimmt auf…",
|
||||||
|
"voiceHoldToTalk": "Zum Sprechen halten",
|
||||||
|
"voiceAutoSend": "Automatisch senden",
|
||||||
|
"voiceTranscript": "Transkript",
|
||||||
|
"voicePromptSpeakNow": "Jetzt sprechen…",
|
||||||
|
"voicePromptTapStart": "Tippe auf \"Starten\", um zu beginnen",
|
||||||
|
"voiceActionStop": "Stopp",
|
||||||
|
"voiceActionStart": "Starten",
|
||||||
"messageInputLabel": "Nachrichteneingabe",
|
"messageInputLabel": "Nachrichteneingabe",
|
||||||
"messageInputHint": "Nachricht eingeben",
|
"messageInputHint": "Nachricht eingeben",
|
||||||
"messageHintText": "Nachricht...",
|
"messageHintText": "Nachricht...",
|
||||||
"stopGenerating": "Generierung stoppen",
|
"stopGenerating": "Generierung stoppen",
|
||||||
|
"codeCopiedToClipboard": "Code in die Zwischenablage kopiert.",
|
||||||
"send": "Senden",
|
"send": "Senden",
|
||||||
"sendMessage": "Nachricht senden",
|
"sendMessage": "Nachricht senden",
|
||||||
"file": "Datei",
|
"file": "Datei",
|
||||||
@@ -289,6 +301,9 @@
|
|||||||
"appCustomization": "App-Anpassung",
|
"appCustomization": "App-Anpassung",
|
||||||
"appCustomizationSubtitle": "Personalisieren, wie Namen und UI angezeigt werden",
|
"appCustomizationSubtitle": "Personalisieren, wie Namen und UI angezeigt werden",
|
||||||
"quickActionsDescription": "Wähle bis zu zwei Schnellzugriffe, die neben dem Eingabefeld angepinnt werden",
|
"quickActionsDescription": "Wähle bis zu zwei Schnellzugriffe, die neben dem Eingabefeld angepinnt werden",
|
||||||
|
"chatSettings": "Chat",
|
||||||
|
"sendOnEnter": "Mit Enter senden",
|
||||||
|
"sendOnEnterDescription": "Enter sendet (Soft-Tastatur). Cmd/Ctrl+Enter ebenfalls verfügbar",
|
||||||
"display": "Anzeige",
|
"display": "Anzeige",
|
||||||
"realtime": "Echtzeit",
|
"realtime": "Echtzeit",
|
||||||
"transportMode": "Transportmodus",
|
"transportMode": "Transportmodus",
|
||||||
|
|||||||
@@ -273,10 +273,52 @@
|
|||||||
,
|
,
|
||||||
"addAttachment": "Add attachment",
|
"addAttachment": "Add attachment",
|
||||||
"@addAttachment": {"description": "Button to add an attachment (file/photo)."},
|
"@addAttachment": {"description": "Button to add an attachment (file/photo)."},
|
||||||
|
"attachmentLabel": "Attachment",
|
||||||
|
"@attachmentLabel": {
|
||||||
|
"description": "Label shown beside attachment chips in messages."
|
||||||
|
},
|
||||||
"tools": "Tools",
|
"tools": "Tools",
|
||||||
"@tools": {"description": "Header for a tools/actions section."},
|
"@tools": {"description": "Header for a tools/actions section."},
|
||||||
"voiceInput": "Voice input",
|
"voiceInput": "Voice input",
|
||||||
"@voiceInput": {"description": "Label for voice input feature."},
|
"@voiceInput": {"description": "Label for voice input feature."},
|
||||||
|
"voice": "Voice",
|
||||||
|
"@voice": {"description": "Title for the voice input bottom sheet."},
|
||||||
|
"voiceStatusListening": "Listening…",
|
||||||
|
"@voiceStatusListening": {
|
||||||
|
"description": "Indicates the app is actively listening during voice input."
|
||||||
|
},
|
||||||
|
"voiceStatusRecording": "Recording…",
|
||||||
|
"@voiceStatusRecording": {
|
||||||
|
"description": "Indicates the app is recording audio for speech recognition."
|
||||||
|
},
|
||||||
|
"voiceHoldToTalk": "Hold to talk",
|
||||||
|
"@voiceHoldToTalk": {
|
||||||
|
"description": "Toggle label for hold-to-talk mode in voice input."
|
||||||
|
},
|
||||||
|
"voiceAutoSend": "Auto-send",
|
||||||
|
"@voiceAutoSend": {
|
||||||
|
"description": "Toggle label for automatically sending the final transcript."
|
||||||
|
},
|
||||||
|
"voiceTranscript": "Transcript",
|
||||||
|
"@voiceTranscript": {
|
||||||
|
"description": "Label above the transcribed voice input text."
|
||||||
|
},
|
||||||
|
"voicePromptSpeakNow": "Speak now…",
|
||||||
|
"@voicePromptSpeakNow": {
|
||||||
|
"description": "Placeholder prompting the user to start speaking."
|
||||||
|
},
|
||||||
|
"voicePromptTapStart": "Tap Start to begin",
|
||||||
|
"@voicePromptTapStart": {
|
||||||
|
"description": "Placeholder instructing the user to tap Start to begin recording."
|
||||||
|
},
|
||||||
|
"voiceActionStop": "Stop",
|
||||||
|
"@voiceActionStop": {
|
||||||
|
"description": "Button label to stop voice recording."
|
||||||
|
},
|
||||||
|
"voiceActionStart": "Start",
|
||||||
|
"@voiceActionStart": {
|
||||||
|
"description": "Button label to start voice recording."
|
||||||
|
},
|
||||||
"messageInputLabel": "Message input",
|
"messageInputLabel": "Message input",
|
||||||
"@messageInputLabel": {"description": "Accessibility label for the message input."},
|
"@messageInputLabel": {"description": "Accessibility label for the message input."},
|
||||||
"messageInputHint": "Type your message",
|
"messageInputHint": "Type your message",
|
||||||
@@ -287,6 +329,10 @@
|
|||||||
"@stopGenerating": {"description": "Action to stop the assistant's response generation."},
|
"@stopGenerating": {"description": "Action to stop the assistant's response generation."},
|
||||||
"send": "Send",
|
"send": "Send",
|
||||||
"@send": {"description": "Primary action to send a message."},
|
"@send": {"description": "Primary action to send a message."},
|
||||||
|
"codeCopiedToClipboard": "Code copied to clipboard.",
|
||||||
|
"@codeCopiedToClipboard": {
|
||||||
|
"description": "Snack bar message confirming code was copied."
|
||||||
|
},
|
||||||
"sendMessage": "Send message",
|
"sendMessage": "Send message",
|
||||||
"@sendMessage": {"description": "Semantic label for sending a message."},
|
"@sendMessage": {"description": "Semantic label for sending a message."},
|
||||||
"file": "File",
|
"file": "File",
|
||||||
@@ -580,6 +626,14 @@
|
|||||||
"@appCustomizationSubtitle": {"description": "Subtitle shown under App Customization tile and page header."},
|
"@appCustomizationSubtitle": {"description": "Subtitle shown under App Customization tile and page header."},
|
||||||
"quickActionsDescription": "Pick up to two shortcuts to pin near the composer",
|
"quickActionsDescription": "Pick up to two shortcuts to pin near the composer",
|
||||||
"@quickActionsDescription": {"description": "Helper text explaining quick action pill selection in customization."},
|
"@quickActionsDescription": {"description": "Helper text explaining quick action pill selection in customization."},
|
||||||
|
"chatSettings": "Chat",
|
||||||
|
"@chatSettings": {"description": "Section header for chat-related customization options."},
|
||||||
|
"sendOnEnter": "Send on Enter",
|
||||||
|
"@sendOnEnter": {"description": "Toggle title for sending messages when pressing Enter."},
|
||||||
|
"sendOnEnterDescription": "Enter sends (soft keyboard). Cmd/Ctrl+Enter also available",
|
||||||
|
"@sendOnEnterDescription": {
|
||||||
|
"description": "Explanation of how the Send on Enter toggle behaves."
|
||||||
|
},
|
||||||
"display": "Display",
|
"display": "Display",
|
||||||
"@display": {"description": "Section header for visual and layout related settings."},
|
"@display": {"description": "Section header for visual and layout related settings."},
|
||||||
"realtime": "Realtime",
|
"realtime": "Realtime",
|
||||||
|
|||||||
@@ -127,12 +127,24 @@
|
|||||||
"onboardQuickBullet2": "Lancez Nouveau chat ou gérez les modèles depuis la barre"
|
"onboardQuickBullet2": "Lancez Nouveau chat ou gérez les modèles depuis la barre"
|
||||||
,
|
,
|
||||||
"addAttachment": "Ajouter une pièce jointe",
|
"addAttachment": "Ajouter une pièce jointe",
|
||||||
|
"attachmentLabel": "Pièce jointe",
|
||||||
"tools": "Outils",
|
"tools": "Outils",
|
||||||
"voiceInput": "Entrée vocale",
|
"voiceInput": "Entrée vocale",
|
||||||
|
"voice": "Voix",
|
||||||
|
"voiceStatusListening": "Écoute…",
|
||||||
|
"voiceStatusRecording": "Enregistrement…",
|
||||||
|
"voiceHoldToTalk": "Maintenir pour parler",
|
||||||
|
"voiceAutoSend": "Envoi automatique",
|
||||||
|
"voiceTranscript": "Transcription",
|
||||||
|
"voicePromptSpeakNow": "Parlez maintenant…",
|
||||||
|
"voicePromptTapStart": "Appuyez sur \"Démarrer\" pour commencer",
|
||||||
|
"voiceActionStop": "Arrêter",
|
||||||
|
"voiceActionStart": "Démarrer",
|
||||||
"messageInputLabel": "Saisie du message",
|
"messageInputLabel": "Saisie du message",
|
||||||
"messageInputHint": "Saisissez votre message",
|
"messageInputHint": "Saisissez votre message",
|
||||||
"messageHintText": "Message...",
|
"messageHintText": "Message...",
|
||||||
"stopGenerating": "Arrêter la génération",
|
"stopGenerating": "Arrêter la génération",
|
||||||
|
"codeCopiedToClipboard": "Code copié dans le presse-papiers.",
|
||||||
"send": "Envoyer",
|
"send": "Envoyer",
|
||||||
"sendMessage": "Envoyer le message",
|
"sendMessage": "Envoyer le message",
|
||||||
"file": "Fichier",
|
"file": "Fichier",
|
||||||
@@ -289,6 +301,9 @@
|
|||||||
"appCustomization": "Personnalisation de l'app",
|
"appCustomization": "Personnalisation de l'app",
|
||||||
"appCustomizationSubtitle": "Personnalisez l'affichage des noms et de l'UI",
|
"appCustomizationSubtitle": "Personnalisez l'affichage des noms et de l'UI",
|
||||||
"quickActionsDescription": "Choisissez jusqu'à deux raccourcis à épingler près du champ de saisie",
|
"quickActionsDescription": "Choisissez jusqu'à deux raccourcis à épingler près du champ de saisie",
|
||||||
|
"chatSettings": "Discussion",
|
||||||
|
"sendOnEnter": "Envoyer avec Entrée",
|
||||||
|
"sendOnEnterDescription": "Entrée envoie (clavier logiciel). Cmd/Ctrl+Entrée aussi disponible",
|
||||||
"display": "Affichage",
|
"display": "Affichage",
|
||||||
"realtime": "Temps réel",
|
"realtime": "Temps réel",
|
||||||
"transportMode": "Mode de transport",
|
"transportMode": "Mode de transport",
|
||||||
|
|||||||
@@ -127,12 +127,24 @@
|
|||||||
"onboardQuickBullet2": "Avvia Nuova chat o gestisci i modelli dalla barra"
|
"onboardQuickBullet2": "Avvia Nuova chat o gestisci i modelli dalla barra"
|
||||||
,
|
,
|
||||||
"addAttachment": "Aggiungi allegato",
|
"addAttachment": "Aggiungi allegato",
|
||||||
|
"attachmentLabel": "Allegato",
|
||||||
"tools": "Strumenti",
|
"tools": "Strumenti",
|
||||||
"voiceInput": "Input vocale",
|
"voiceInput": "Input vocale",
|
||||||
|
"voice": "Voce",
|
||||||
|
"voiceStatusListening": "In ascolto…",
|
||||||
|
"voiceStatusRecording": "Registrazione…",
|
||||||
|
"voiceHoldToTalk": "Tieni premuto per parlare",
|
||||||
|
"voiceAutoSend": "Invio automatico",
|
||||||
|
"voiceTranscript": "Trascrizione",
|
||||||
|
"voicePromptSpeakNow": "Parla ora…",
|
||||||
|
"voicePromptTapStart": "Tocca \"Avvia\" per iniziare",
|
||||||
|
"voiceActionStop": "Stop",
|
||||||
|
"voiceActionStart": "Avvia",
|
||||||
"messageInputLabel": "Input messaggio",
|
"messageInputLabel": "Input messaggio",
|
||||||
"messageInputHint": "Scrivi il tuo messaggio",
|
"messageInputHint": "Scrivi il tuo messaggio",
|
||||||
"messageHintText": "Messaggio...",
|
"messageHintText": "Messaggio...",
|
||||||
"stopGenerating": "Interrompi generazione",
|
"stopGenerating": "Interrompi generazione",
|
||||||
|
"codeCopiedToClipboard": "Codice copiato negli appunti.",
|
||||||
"send": "Invia",
|
"send": "Invia",
|
||||||
"sendMessage": "Invia messaggio",
|
"sendMessage": "Invia messaggio",
|
||||||
"file": "File",
|
"file": "File",
|
||||||
@@ -289,6 +301,9 @@
|
|||||||
"appCustomization": "Personalizzazione app",
|
"appCustomization": "Personalizzazione app",
|
||||||
"appCustomizationSubtitle": "Personalizza la visualizzazione dei nomi e dell'UI",
|
"appCustomizationSubtitle": "Personalizza la visualizzazione dei nomi e dell'UI",
|
||||||
"quickActionsDescription": "Scegli fino a due scorciatoie da fissare vicino al campo di input",
|
"quickActionsDescription": "Scegli fino a due scorciatoie da fissare vicino al campo di input",
|
||||||
|
"chatSettings": "Chat",
|
||||||
|
"sendOnEnter": "Invia con Invio",
|
||||||
|
"sendOnEnterDescription": "Invio invia (tastiera software). Cmd/Ctrl+Invio disponibile",
|
||||||
"display": "Schermo",
|
"display": "Schermo",
|
||||||
"realtime": "Tempo reale",
|
"realtime": "Tempo reale",
|
||||||
"transportMode": "Modalità di trasporto",
|
"transportMode": "Modalità di trasporto",
|
||||||
|
|||||||
@@ -804,6 +804,12 @@ abstract class AppLocalizations {
|
|||||||
/// **'Add attachment'**
|
/// **'Add attachment'**
|
||||||
String get addAttachment;
|
String get addAttachment;
|
||||||
|
|
||||||
|
/// Label shown beside attachment chips in messages.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Attachment'**
|
||||||
|
String get attachmentLabel;
|
||||||
|
|
||||||
/// Header for a tools/actions section.
|
/// Header for a tools/actions section.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
@@ -816,6 +822,66 @@ abstract class AppLocalizations {
|
|||||||
/// **'Voice input'**
|
/// **'Voice input'**
|
||||||
String get voiceInput;
|
String get voiceInput;
|
||||||
|
|
||||||
|
/// Title for the voice input bottom sheet.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Voice'**
|
||||||
|
String get voice;
|
||||||
|
|
||||||
|
/// Indicates the app is actively listening during voice input.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Listening…'**
|
||||||
|
String get voiceStatusListening;
|
||||||
|
|
||||||
|
/// Indicates the app is recording audio for speech recognition.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Recording…'**
|
||||||
|
String get voiceStatusRecording;
|
||||||
|
|
||||||
|
/// Toggle label for hold-to-talk mode in voice input.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Hold to talk'**
|
||||||
|
String get voiceHoldToTalk;
|
||||||
|
|
||||||
|
/// Toggle label for automatically sending the final transcript.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Auto-send'**
|
||||||
|
String get voiceAutoSend;
|
||||||
|
|
||||||
|
/// Label above the transcribed voice input text.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Transcript'**
|
||||||
|
String get voiceTranscript;
|
||||||
|
|
||||||
|
/// Placeholder prompting the user to start speaking.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Speak now…'**
|
||||||
|
String get voicePromptSpeakNow;
|
||||||
|
|
||||||
|
/// Placeholder instructing the user to tap Start to begin recording.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Tap Start to begin'**
|
||||||
|
String get voicePromptTapStart;
|
||||||
|
|
||||||
|
/// Button label to stop voice recording.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Stop'**
|
||||||
|
String get voiceActionStop;
|
||||||
|
|
||||||
|
/// Button label to start voice recording.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Start'**
|
||||||
|
String get voiceActionStart;
|
||||||
|
|
||||||
/// Accessibility label for the message input.
|
/// Accessibility label for the message input.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
@@ -846,6 +912,12 @@ abstract class AppLocalizations {
|
|||||||
/// **'Send'**
|
/// **'Send'**
|
||||||
String get send;
|
String get send;
|
||||||
|
|
||||||
|
/// Snack bar message confirming code was copied.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Code copied to clipboard.'**
|
||||||
|
String get codeCopiedToClipboard;
|
||||||
|
|
||||||
/// Semantic label for sending a message.
|
/// Semantic label for sending a message.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
@@ -1584,6 +1656,24 @@ abstract class AppLocalizations {
|
|||||||
/// **'Pick up to two shortcuts to pin near the composer'**
|
/// **'Pick up to two shortcuts to pin near the composer'**
|
||||||
String get quickActionsDescription;
|
String get quickActionsDescription;
|
||||||
|
|
||||||
|
/// Section header for chat-related customization options.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Chat'**
|
||||||
|
String get chatSettings;
|
||||||
|
|
||||||
|
/// Toggle title for sending messages when pressing Enter.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Send on Enter'**
|
||||||
|
String get sendOnEnter;
|
||||||
|
|
||||||
|
/// Explanation of how the Send on Enter toggle behaves.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Enter sends (soft keyboard). Cmd/Ctrl+Enter also available'**
|
||||||
|
String get sendOnEnterDescription;
|
||||||
|
|
||||||
/// Section header for visual and layout related settings.
|
/// Section header for visual and layout related settings.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
|
|||||||
@@ -405,12 +405,45 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get addAttachment => 'Anhang hinzufügen';
|
String get addAttachment => 'Anhang hinzufügen';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get attachmentLabel => 'Anhang';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get tools => 'Werkzeuge';
|
String get tools => 'Werkzeuge';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get voiceInput => 'Spracheingabe';
|
String get voiceInput => 'Spracheingabe';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voice => 'Sprache';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voiceStatusListening => 'Hört zu…';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voiceStatusRecording => 'Nimmt auf…';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voiceHoldToTalk => 'Zum Sprechen halten';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voiceAutoSend => 'Automatisch senden';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voiceTranscript => 'Transkript';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voicePromptSpeakNow => 'Jetzt sprechen…';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voicePromptTapStart => 'Tippe auf \"Starten\", um zu beginnen';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voiceActionStop => 'Stopp';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voiceActionStart => 'Starten';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get messageInputLabel => 'Nachrichteneingabe';
|
String get messageInputLabel => 'Nachrichteneingabe';
|
||||||
|
|
||||||
@@ -426,6 +459,9 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get send => 'Senden';
|
String get send => 'Senden';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get codeCopiedToClipboard => 'Code in die Zwischenablage kopiert.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get sendMessage => 'Nachricht senden';
|
String get sendMessage => 'Nachricht senden';
|
||||||
|
|
||||||
@@ -829,6 +865,16 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||||||
String get quickActionsDescription =>
|
String get quickActionsDescription =>
|
||||||
'Wähle bis zu zwei Schnellzugriffe, die neben dem Eingabefeld angepinnt werden';
|
'Wähle bis zu zwei Schnellzugriffe, die neben dem Eingabefeld angepinnt werden';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get chatSettings => 'Chat';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get sendOnEnter => 'Mit Enter senden';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get sendOnEnterDescription =>
|
||||||
|
'Enter sendet (Soft-Tastatur). Cmd/Ctrl+Enter ebenfalls verfügbar';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get display => 'Anzeige';
|
String get display => 'Anzeige';
|
||||||
|
|
||||||
|
|||||||
@@ -400,12 +400,45 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get addAttachment => 'Add attachment';
|
String get addAttachment => 'Add attachment';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get attachmentLabel => 'Attachment';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get tools => 'Tools';
|
String get tools => 'Tools';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get voiceInput => 'Voice input';
|
String get voiceInput => 'Voice input';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voice => 'Voice';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voiceStatusListening => 'Listening…';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voiceStatusRecording => 'Recording…';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voiceHoldToTalk => 'Hold to talk';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voiceAutoSend => 'Auto-send';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voiceTranscript => 'Transcript';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voicePromptSpeakNow => 'Speak now…';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voicePromptTapStart => 'Tap Start to begin';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voiceActionStop => 'Stop';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voiceActionStart => 'Start';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get messageInputLabel => 'Message input';
|
String get messageInputLabel => 'Message input';
|
||||||
|
|
||||||
@@ -421,6 +454,9 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get send => 'Send';
|
String get send => 'Send';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get codeCopiedToClipboard => 'Code copied to clipboard.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get sendMessage => 'Send message';
|
String get sendMessage => 'Send message';
|
||||||
|
|
||||||
@@ -822,6 +858,16 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
String get quickActionsDescription =>
|
String get quickActionsDescription =>
|
||||||
'Pick up to two shortcuts to pin near the composer';
|
'Pick up to two shortcuts to pin near the composer';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get chatSettings => 'Chat';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get sendOnEnter => 'Send on Enter';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get sendOnEnterDescription =>
|
||||||
|
'Enter sends (soft keyboard). Cmd/Ctrl+Enter also available';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get display => 'Display';
|
String get display => 'Display';
|
||||||
|
|
||||||
|
|||||||
@@ -410,12 +410,45 @@ class AppLocalizationsFr extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get addAttachment => 'Ajouter une pièce jointe';
|
String get addAttachment => 'Ajouter une pièce jointe';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get attachmentLabel => 'Pièce jointe';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get tools => 'Outils';
|
String get tools => 'Outils';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get voiceInput => 'Entrée vocale';
|
String get voiceInput => 'Entrée vocale';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voice => 'Voix';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voiceStatusListening => 'Écoute…';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voiceStatusRecording => 'Enregistrement…';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voiceHoldToTalk => 'Maintenir pour parler';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voiceAutoSend => 'Envoi automatique';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voiceTranscript => 'Transcription';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voicePromptSpeakNow => 'Parlez maintenant…';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voicePromptTapStart => 'Appuyez sur \"Démarrer\" pour commencer';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voiceActionStop => 'Arrêter';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voiceActionStart => 'Démarrer';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get messageInputLabel => 'Saisie du message';
|
String get messageInputLabel => 'Saisie du message';
|
||||||
|
|
||||||
@@ -431,6 +464,9 @@ class AppLocalizationsFr extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get send => 'Envoyer';
|
String get send => 'Envoyer';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get codeCopiedToClipboard => 'Code copié dans le presse-papiers.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get sendMessage => 'Envoyer le message';
|
String get sendMessage => 'Envoyer le message';
|
||||||
|
|
||||||
@@ -837,6 +873,16 @@ class AppLocalizationsFr extends AppLocalizations {
|
|||||||
String get quickActionsDescription =>
|
String get quickActionsDescription =>
|
||||||
'Choisissez jusqu\'à deux raccourcis à épingler près du champ de saisie';
|
'Choisissez jusqu\'à deux raccourcis à épingler près du champ de saisie';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get chatSettings => 'Discussion';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get sendOnEnter => 'Envoyer avec Entrée';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get sendOnEnterDescription =>
|
||||||
|
'Entrée envoie (clavier logiciel). Cmd/Ctrl+Entrée aussi disponible';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get display => 'Affichage';
|
String get display => 'Affichage';
|
||||||
|
|
||||||
|
|||||||
@@ -402,12 +402,45 @@ class AppLocalizationsIt extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get addAttachment => 'Aggiungi allegato';
|
String get addAttachment => 'Aggiungi allegato';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get attachmentLabel => 'Allegato';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get tools => 'Strumenti';
|
String get tools => 'Strumenti';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get voiceInput => 'Input vocale';
|
String get voiceInput => 'Input vocale';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voice => 'Voce';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voiceStatusListening => 'In ascolto…';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voiceStatusRecording => 'Registrazione…';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voiceHoldToTalk => 'Tieni premuto per parlare';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voiceAutoSend => 'Invio automatico';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voiceTranscript => 'Trascrizione';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voicePromptSpeakNow => 'Parla ora…';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voicePromptTapStart => 'Tocca \"Avvia\" per iniziare';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voiceActionStop => 'Stop';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get voiceActionStart => 'Avvia';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get messageInputLabel => 'Input messaggio';
|
String get messageInputLabel => 'Input messaggio';
|
||||||
|
|
||||||
@@ -423,6 +456,9 @@ class AppLocalizationsIt extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get send => 'Invia';
|
String get send => 'Invia';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get codeCopiedToClipboard => 'Codice copiato negli appunti.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get sendMessage => 'Invia messaggio';
|
String get sendMessage => 'Invia messaggio';
|
||||||
|
|
||||||
@@ -826,6 +862,16 @@ class AppLocalizationsIt extends AppLocalizations {
|
|||||||
String get quickActionsDescription =>
|
String get quickActionsDescription =>
|
||||||
'Scegli fino a due scorciatoie da fissare vicino al campo di input';
|
'Scegli fino a due scorciatoie da fissare vicino al campo di input';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get chatSettings => 'Chat';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get sendOnEnter => 'Invia con Invio';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get sendOnEnterDescription =>
|
||||||
|
'Invio invia (tastiera software). Cmd/Ctrl+Invio disponibile';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get display => 'Schermo';
|
String get display => 'Schermo';
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import 'package:flutter_math_fork/flutter_math.dart';
|
|||||||
import 'package:markdown/markdown.dart' as md;
|
import 'package:markdown/markdown.dart' as md;
|
||||||
import 'package:webview_flutter/webview_flutter.dart';
|
import 'package:webview_flutter/webview_flutter.dart';
|
||||||
|
|
||||||
|
import 'package:conduit/l10n/app_localizations.dart';
|
||||||
|
|
||||||
import '../../theme/color_tokens.dart';
|
import '../../theme/color_tokens.dart';
|
||||||
import '../../theme/theme_extensions.dart';
|
import '../../theme/theme_extensions.dart';
|
||||||
import 'code_block_header.dart';
|
import 'code_block_header.dart';
|
||||||
@@ -76,18 +78,10 @@ class ConduitMarkdown {
|
|||||||
|
|
||||||
return MarkdownStyleSheet(
|
return MarkdownStyleSheet(
|
||||||
p: baseBody,
|
p: baseBody,
|
||||||
h1: AppTypography.headlineLargeStyle.copyWith(
|
h1: AppTypography.headlineLargeStyle.copyWith(color: theme.textPrimary),
|
||||||
color: theme.textPrimary,
|
h2: AppTypography.headlineMediumStyle.copyWith(color: theme.textPrimary),
|
||||||
),
|
h3: AppTypography.headlineSmallStyle.copyWith(color: theme.textPrimary),
|
||||||
h2: AppTypography.headlineMediumStyle.copyWith(
|
h4: AppTypography.bodyLargeStyle.copyWith(color: theme.textPrimary),
|
||||||
color: theme.textPrimary,
|
|
||||||
),
|
|
||||||
h3: AppTypography.headlineSmallStyle.copyWith(
|
|
||||||
color: theme.textPrimary,
|
|
||||||
),
|
|
||||||
h4: AppTypography.bodyLargeStyle.copyWith(
|
|
||||||
color: theme.textPrimary,
|
|
||||||
),
|
|
||||||
h5: baseBody.copyWith(fontWeight: FontWeight.w600),
|
h5: baseBody.copyWith(fontWeight: FontWeight.w600),
|
||||||
h6: secondaryBody,
|
h6: secondaryBody,
|
||||||
a: baseBody.copyWith(
|
a: baseBody.copyWith(
|
||||||
@@ -122,7 +116,10 @@ class ConduitMarkdown {
|
|||||||
listIndent: Spacing.lg,
|
listIndent: Spacing.lg,
|
||||||
tableHead: secondaryBody.copyWith(fontWeight: FontWeight.w600),
|
tableHead: secondaryBody.copyWith(fontWeight: FontWeight.w600),
|
||||||
tableBody: secondaryBody,
|
tableBody: secondaryBody,
|
||||||
tableBorder: TableBorder.all(color: borderColor, width: BorderWidth.micro),
|
tableBorder: TableBorder.all(
|
||||||
|
color: borderColor,
|
||||||
|
width: BorderWidth.micro,
|
||||||
|
),
|
||||||
tableHeadAlign: TextAlign.start,
|
tableHeadAlign: TextAlign.start,
|
||||||
tableColumnWidth: const FlexColumnWidth(),
|
tableColumnWidth: const FlexColumnWidth(),
|
||||||
tableCellsPadding: const EdgeInsets.symmetric(
|
tableCellsPadding: const EdgeInsets.symmetric(
|
||||||
@@ -131,10 +128,7 @@ class ConduitMarkdown {
|
|||||||
),
|
),
|
||||||
horizontalRuleDecoration: BoxDecoration(
|
horizontalRuleDecoration: BoxDecoration(
|
||||||
border: Border(
|
border: Border(
|
||||||
top: BorderSide(
|
top: BorderSide(color: theme.dividerColor, width: BorderWidth.small),
|
||||||
color: theme.dividerColor,
|
|
||||||
width: BorderWidth.small,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -153,9 +147,7 @@ class ConduitMarkdown {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static List<md.InlineSyntax> _buildInlineSyntaxes() {
|
static List<md.InlineSyntax> _buildInlineSyntaxes() {
|
||||||
return [
|
return [_LatexInlineSyntax()];
|
||||||
_LatexInlineSyntax(),
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Widget buildMermaidBlock(BuildContext context, String code) {
|
static Widget buildMermaidBlock(BuildContext context, String code) {
|
||||||
@@ -243,7 +235,9 @@ class ConduitMarkdown {
|
|||||||
textAlign: TextAlign.left,
|
textAlign: TextAlign.left,
|
||||||
textDirection: TextDirection.ltr,
|
textDirection: TextDirection.ltr,
|
||||||
textWidthBasis: TextWidthBasis.parent,
|
textWidthBasis: TextWidthBasis.parent,
|
||||||
style: AppTypography.codeStyle.copyWith(color: conduitTheme.codeText),
|
style: AppTypography.codeStyle.copyWith(
|
||||||
|
color: conduitTheme.codeText,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -279,8 +273,12 @@ class _CodeBlockBuilder extends MarkdownElementBuilder {
|
|||||||
final theme = context.conduitTheme;
|
final theme = context.conduitTheme;
|
||||||
final isDark = Theme.of(context).brightness == Brightness.dark;
|
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||||
final code = element.textContent;
|
final code = element.textContent;
|
||||||
final language = element.attributes['class']?.replaceFirst('language-', '') ?? 'plaintext';
|
final language =
|
||||||
final normalizedLanguage = language.trim().isEmpty ? 'plaintext' : language.trim();
|
element.attributes['class']?.replaceFirst('language-', '') ??
|
||||||
|
'plaintext';
|
||||||
|
final normalizedLanguage = language.trim().isEmpty
|
||||||
|
? 'plaintext'
|
||||||
|
: language.trim();
|
||||||
|
|
||||||
// Match GitHub/Atom theme colors for code block container
|
// Match GitHub/Atom theme colors for code block container
|
||||||
final codeBackground = isDark
|
final codeBackground = isDark
|
||||||
@@ -306,9 +304,12 @@ class _CodeBlockBuilder extends MarkdownElementBuilder {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ScaffoldMessenger.of(context).hideCurrentSnackBar();
|
ScaffoldMessenger.of(context).hideCurrentSnackBar();
|
||||||
|
final l10n = AppLocalizations.of(context);
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(
|
SnackBar(
|
||||||
content: Text('Code copied to clipboard.'),
|
content: Text(
|
||||||
|
l10n?.codeCopiedToClipboard ?? 'Code copied to clipboard.',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -365,7 +366,10 @@ class _ImageBuilder extends MarkdownElementBuilder {
|
|||||||
try {
|
try {
|
||||||
final commaIndex = dataUrl.indexOf(',');
|
final commaIndex = dataUrl.indexOf(',');
|
||||||
if (commaIndex == -1) {
|
if (commaIndex == -1) {
|
||||||
throw const FormatException('Invalid data URL format');
|
throw FormatException(
|
||||||
|
AppLocalizations.of(context)?.invalidDataUrl ??
|
||||||
|
'Invalid data URL format',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final base64String = dataUrl.substring(commaIndex + 1);
|
final base64String = dataUrl.substring(commaIndex + 1);
|
||||||
@@ -421,10 +425,7 @@ class _ImageBuilder extends MarkdownElementBuilder {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildImageError(
|
Widget _buildImageError(BuildContext context, ConduitThemeExtension theme) {
|
||||||
BuildContext context,
|
|
||||||
ConduitThemeExtension theme,
|
|
||||||
) {
|
|
||||||
return Container(
|
return Container(
|
||||||
height: 120,
|
height: 120,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
@@ -467,9 +468,8 @@ class _LatexBuilder extends MarkdownElementBuilder {
|
|||||||
final content = element.textContent.trim();
|
final content = element.textContent.trim();
|
||||||
final isInline = element.attributes['isInline'] == 'true';
|
final isInline = element.attributes['isInline'] == 'true';
|
||||||
|
|
||||||
final baseStyle = (preferredStyle ?? AppTypography.bodyMediumStyle).copyWith(
|
final baseStyle = (preferredStyle ?? AppTypography.bodyMediumStyle)
|
||||||
color: isDark ? Colors.white : Colors.black,
|
.copyWith(color: isDark ? Colors.white : Colors.black);
|
||||||
);
|
|
||||||
|
|
||||||
if (content.isEmpty) {
|
if (content.isEmpty) {
|
||||||
return Text(element.textContent, style: baseStyle);
|
return Text(element.textContent, style: baseStyle);
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:conduit/l10n/app_localizations.dart';
|
||||||
|
|
||||||
import '../theme/theme_extensions.dart';
|
import '../theme/theme_extensions.dart';
|
||||||
|
|
||||||
/// Centralized helper for building themed dialogs consistently
|
/// Centralized helper for building themed dialogs consistently
|
||||||
@@ -31,11 +34,14 @@ class ThemedDialogs {
|
|||||||
BuildContext context, {
|
BuildContext context, {
|
||||||
required String title,
|
required String title,
|
||||||
required String message,
|
required String message,
|
||||||
String confirmText = 'Confirm',
|
String? confirmText,
|
||||||
String cancelText = 'Cancel',
|
String? cancelText,
|
||||||
bool isDestructive = false,
|
bool isDestructive = false,
|
||||||
bool barrierDismissible = true,
|
bool barrierDismissible = true,
|
||||||
}) async {
|
}) async {
|
||||||
|
final l10n = AppLocalizations.of(context);
|
||||||
|
final effectiveConfirmText = confirmText ?? l10n?.confirm ?? 'Confirm';
|
||||||
|
final effectiveCancelText = cancelText ?? l10n?.cancel ?? 'Cancel';
|
||||||
final result = await showDialog<bool>(
|
final result = await showDialog<bool>(
|
||||||
context: context,
|
context: context,
|
||||||
barrierDismissible: barrierDismissible,
|
barrierDismissible: barrierDismissible,
|
||||||
@@ -50,7 +56,7 @@ class ThemedDialogs {
|
|||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.of(ctx).pop(false),
|
onPressed: () => Navigator.of(ctx).pop(false),
|
||||||
child: Text(
|
child: Text(
|
||||||
cancelText,
|
effectiveCancelText,
|
||||||
style: TextStyle(color: ctx.conduitTheme.textSecondary),
|
style: TextStyle(color: ctx.conduitTheme.textSecondary),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -62,7 +68,7 @@ class ThemedDialogs {
|
|||||||
: ctx.conduitTheme.buttonPrimary,
|
: ctx.conduitTheme.buttonPrimary,
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
confirmText,
|
effectiveConfirmText,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: isDestructive
|
color: isDestructive
|
||||||
? ctx.conduitTheme.error
|
? ctx.conduitTheme.error
|
||||||
@@ -103,8 +109,8 @@ class ThemedDialogs {
|
|||||||
required String title,
|
required String title,
|
||||||
required String hintText,
|
required String hintText,
|
||||||
String? initialValue,
|
String? initialValue,
|
||||||
String confirmText = 'Save',
|
String? confirmText,
|
||||||
String cancelText = 'Cancel',
|
String? cancelText,
|
||||||
bool barrierDismissible = true,
|
bool barrierDismissible = true,
|
||||||
TextInputType? keyboardType,
|
TextInputType? keyboardType,
|
||||||
TextCapitalization textCapitalization = TextCapitalization.sentences,
|
TextCapitalization textCapitalization = TextCapitalization.sentences,
|
||||||
@@ -112,6 +118,9 @@ class ThemedDialogs {
|
|||||||
}) async {
|
}) async {
|
||||||
final theme = context.conduitTheme;
|
final theme = context.conduitTheme;
|
||||||
final controller = TextEditingController(text: initialValue ?? '');
|
final controller = TextEditingController(text: initialValue ?? '');
|
||||||
|
final l10n = AppLocalizations.of(context);
|
||||||
|
final effectiveConfirmText = confirmText ?? l10n?.save ?? 'Save';
|
||||||
|
final effectiveCancelText = cancelText ?? l10n?.cancel ?? 'Cancel';
|
||||||
|
|
||||||
String? result = await showDialog<String>(
|
String? result = await showDialog<String>(
|
||||||
context: context,
|
context: context,
|
||||||
@@ -169,7 +178,7 @@ class ThemedDialogs {
|
|||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.of(ctx).pop(),
|
onPressed: () => Navigator.of(ctx).pop(),
|
||||||
child: Text(
|
child: Text(
|
||||||
cancelText,
|
effectiveCancelText,
|
||||||
style: TextStyle(color: theme.textSecondary),
|
style: TextStyle(color: theme.textSecondary),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -185,7 +194,7 @@ class ThemedDialogs {
|
|||||||
? () => Navigator.of(ctx).pop(trimmed)
|
? () => Navigator.of(ctx).pop(trimmed)
|
||||||
: null,
|
: null,
|
||||||
child: Text(
|
child: Text(
|
||||||
confirmText,
|
effectiveConfirmText,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: enabled
|
color: enabled
|
||||||
? theme.buttonPrimary
|
? theme.buttonPrimary
|
||||||
|
|||||||
Reference in New Issue
Block a user