diff --git a/lib/screen/render.test.ts b/lib/screen/render.test.ts index d806c98..c4163d2 100644 --- a/lib/screen/render.test.ts +++ b/lib/screen/render.test.ts @@ -76,18 +76,30 @@ describe('screenTree', () => { ); }); - it('drops the separator when only one language has something to say', () => { + it('shows whichever language has something to say', () => { const frenchOnly = JSON.stringify( screenTree({ ...PAYLOAD, today: { ...PAYLOAD.today, next_change_en: '' } }), ); expect(frenchOnly).toContain('Ferme à 13:00'); - expect(frenchOnly).not.toContain('"·"'); + expect(frenchOnly).not.toContain('Closes at'); const englishOnly = JSON.stringify( screenTree({ ...PAYLOAD, today: { ...PAYLOAD.today, next_change_fr: '' } }), ); expect(englishOnly).toContain('Closes at 1:00 pm'); - expect(englishOnly).not.toContain('"·"'); + expect(englishOnly).not.toContain('Ferme à'); + }); + + it('shrinks a long next-change line instead of wrapping it', () => { + // The main block is narrower now the week runs down the side; a long + // sentence used to wrap and strand half of itself on a second line. + const long = 'Ouvre lundi à 11:00 après la fermeture annuelle'; + const tree = JSON.stringify( + screenTree({ ...PAYLOAD, today: { ...PAYLOAD.today, next_change_fr: long } }), + ); + const sizes = [...tree.matchAll(/"fontSize":(\d+)/g)].map((match) => Number(match[1])); + // Something on the screen had to come down from the preferred 24. + expect(sizes.some((size) => size < 24 && size >= 18)).toBe(true); }); it('drops the whole next-change line when there is nothing ahead', () => { diff --git a/lib/screen/render.ts b/lib/screen/render.ts index 2732913..d5fa794 100644 --- a/lib/screen/render.ts +++ b/lib/screen/render.ts @@ -220,21 +220,55 @@ function main(payload: ScreenPayload, width: number): ElementNode { today.hours_text, ) : null, - nextChangeLine(payload), + nextChangeLine(payload, width), ); } -function nextChangeLine(payload: ScreenPayload): ElementNode | null { +/** + * "Ferme à 18:30", then the English underneath. + * + * Stacked rather than side by side: the main block is narrower now that the + * week runs down the right, and a row put the two languages in competition + * for the width — the French wrapped and left the separator stranded on the + * next line with half the English. Two lines also match the banner, where + * French above English is already the pattern. + */ +function nextChangeLine(payload: ScreenPayload, width: number): ElementNode | null { const { next_change_fr: fr, next_change_en: en } = payload.today; if (!fr && !en) { return null; } + + const available = width - 2 * PADDING; + return h( 'div', - { style: { display: 'flex', alignItems: 'baseline', marginTop: 12 } }, - fr ? h('div', { style: { display: 'flex', fontSize: 24 } }, fr) : null, - fr && en ? h('div', { style: { display: 'flex', fontSize: 24, paddingLeft: 10, paddingRight: 10 } }, '·') : null, - en ? h('div', { style: { display: 'flex', fontSize: 20 } }, en) : null, + { style: { display: 'flex', flexDirection: 'column', marginTop: 12 } }, + fr + ? h( + 'div', + { + style: { + display: 'flex', + fontSize: fitFontSize(fr, { available, preferred: 24, minimum: 18 }), + }, + }, + fr, + ) + : null, + en + ? h( + 'div', + { + style: { + display: 'flex', + fontSize: fitFontSize(en, { available, preferred: 20, minimum: 15 }), + marginTop: 2, + }, + }, + en, + ) + : null, ); }