diff --git a/locales/rn/en.json b/locales/rn/en.json index 0fd2d22e..415b2bdd 100644 --- a/locales/rn/en.json +++ b/locales/rn/en.json @@ -136,6 +136,10 @@ "send_now": "Send now", "send_timeout_body": "The message may already have gone out. Check your Sent folder before sending it again.", "send_timeout_title": "No answer from the server", + "toolbar": { + "background_color": "Background color", + "remove_background_color": "Remove background color" + }, "undo_send_label": "Sending in {seconds}s…", "uploading": "Uploading...", "validation": { diff --git a/src/components/RichTextEditor.tsx b/src/components/RichTextEditor.tsx index 2590edfb..ce416986 100644 --- a/src/components/RichTextEditor.tsx +++ b/src/components/RichTextEditor.tsx @@ -23,7 +23,9 @@ export type RichTextCommand = | 'undo' | 'redo' // Text colour: a CSS colour after the colon, e.g. 'foreColor:#d97706'. - | `foreColor:${string}`; + | `foreColor:${string}` + // Background colour, the same way; 'hiliteColor:transparent' removes it. + | `hiliteColor:${string}`; export interface RichTextSelectionState { bold: boolean; diff --git a/src/screens/ComposeScreen.tsx b/src/screens/ComposeScreen.tsx index b8166204..e489750c 100644 --- a/src/screens/ComposeScreen.tsx +++ b/src/screens/ComposeScreen.tsx @@ -11,7 +11,7 @@ import { List, ListOrdered, Link2, Link2Off, Image as ImageIcon, Quote, Heading1, Heading2, AlignLeft, AlignCenter, AlignRight, RemoveFormatting, Undo2, Redo2, FileText, Clock, Check, Palette, Table, LayoutTemplate, MailCheck, - Users, Tag, Type, + Users, Tag, Type, Highlighter, } from 'lucide-react-native'; import DateTimePicker, { type DateTimePickerEvent } from '@react-native-community/datetimepicker'; import * as ImagePicker from 'expo-image-picker'; @@ -103,7 +103,11 @@ type Field = 'to' | 'cc' | 'bcc'; const URL_RE = /^https?:\/\/.+/i; -const TEXT_COLORS = ['#000000', '#6b7280', '#dc2626', '#ea580c', '#ca8a04', '#16a34a', '#2563eb', '#7c3aed']; +// The webmail's 2 x 8 palette, used for text and background colour alike. +const TEXT_COLORS = [ + '#000000', '#5f6368', '#9aa0a6', '#c5221f', '#e8710a', '#f9ab00', '#188038', '#1967d2', + '#7627bb', '#c2185b', '#795548', '#fa5252', '#fd7e14', '#40c057', '#4dabf7', '#e64980', +]; function formatBytes(n: number): string { if (n < 1024) return `${n} B`; @@ -1759,7 +1763,7 @@ export default function ComposeScreen({ route, navigation }: Props) { }; // ── Colour / table ─────────────────────────────────────────────────── - const [colorPickerOpen, setColorPickerOpen] = React.useState(false); + const [colorTarget, setColorTarget] = React.useState<'text' | 'background' | null>(null); const [tableMenuOpen, setTableMenuOpen] = React.useState(false); const insertTable = (rows: number, cols: number) => { const cell = ' '; @@ -2437,8 +2441,12 @@ export default function ComposeScreen({ route, navigation }: Props) { icon={} /> editorRef.current?.exec('strikeThrough')} icon={} /> - setColorPickerOpen(true)} + setColorTarget('text')} + label={t('email_composer.toolbar.text_color', 'Text color')} icon={} /> + setColorTarget('background')} + label={t('email_composer.toolbar.background_color', 'Background color')} + icon={} /> @@ -2539,21 +2547,40 @@ export default function ComposeScreen({ route, navigation }: Props) { - {/* Text colour palette */} - setColorPickerOpen(false)}> - setColorPickerOpen(false)}> + {/* Text / background colour palette */} + setColorTarget(null)}> + setColorTarget(null)}> {}}> - {t('email_composer.toolbar.text_color', 'Text color')} + + {colorTarget === 'background' + ? t('email_composer.toolbar.background_color', 'Background color') + : t('email_composer.toolbar.text_color', 'Text color')} + {TEXT_COLORS.map((color) => ( { setColorPickerOpen(false); editorRef.current?.exec(`foreColor:${color}`); }} + accessibilityLabel={color} + onPress={() => { + setColorTarget(null); + editorRef.current?.exec(colorTarget === 'background' ? `hiliteColor:${color}` : `foreColor:${color}`); + }} style={[styles.swatch, { backgroundColor: color }]} /> ))} - setColorPickerOpen(false)}> + {colorTarget === 'background' && ( + { setColorTarget(null); editorRef.current?.exec('hiliteColor:transparent'); }} + > + + + {t('email_composer.toolbar.remove_background_color', 'Remove background color')} + + + )} + setColorTarget(null)}> {t('email_composer.cancel', 'Cancel')}