fix: green checks after the first-screen redesign and the safe-area floor

- native-shell/amount.ts: the no-break spaces in the price pattern were
  written out as characters; \s already matches them.
- widgets.ts: the Live Activity's lead time stays inside the module.
- i18n: the count strings of the new plan tiles replace the removed ones
  on NOT_PLURAL, and the address placeholders of the non-Latin locales
  are their own instead of English copies.
- mobile.css: the side safe-area margins of the floating bars use
  margin-inline, swapped for right to left, instead of physical sides.
This commit is contained in:
Maurice
2026-11-12 14:36:13 +01:00
parent 9005d6b333
commit fc648bc7e4
11 changed files with 33 additions and 27 deletions
+4 -4
View File
@@ -12,9 +12,9 @@ interface Amount {
render(value: number): string;
}
// Digits with the marks stores put between them: . , space, no-break spaces, and
// the apostrophes Swiss formats group thousands with (1'290 and 1’290).
const NUMBER = /\d[\d.,\s  '’]*\d|\d/;
// Digits with the marks stores put between them: . , any space (\s takes the
// no-break ones too) and the apostrophes Swiss formats group thousands with.
const NUMBER = /\d[\d.,\s'’]*\d|\d/;
export function amountIn(label: string): Amount | null {
const match = NUMBER.exec(label);
@@ -25,7 +25,7 @@ export function amountIn(label: string): Amount | null {
const decimals = decimal ? decimal[2].length : 0;
const mark = decimal ? decimal[1] : '';
const whole = decimal ? raw.slice(0, raw.length - decimal[0].length) : raw;
const group = /[.,\s  '’]/.exec(whole)?.[0] ?? '';
const group = /[.,\s'’]/.exec(whole)?.[0] ?? '';
const digits = whole.replace(/\D/g, '') + (decimal ? `.${decimal[2]}` : '');
const value = Number(digits);
if (!Number.isFinite(value)) return null;
+8 -5
View File
@@ -578,12 +578,15 @@ html[dir='rtl']:has(.m-shell[data-size='wide'], .m-shell[data-size='split']) .m-
inset-inline-end: 0;
}
/* Without the rail the floating bars keep clear of the sides' safe area too:
a camera in a corner can come as a side inset. Physical sides, as the
insets are the screen's, not the text direction's. On a wide window the
rail takes the leading side and a bar may centre itself (mx-auto). */
a camera in a corner can come as a side inset. The insets are the screen's,
not the text direction's, so right to left takes them the other way round.
On a wide window the rail takes the leading side and a bar may centre itself
(mx-auto). */
html:not(:has(.m-shell[data-size='wide'], .m-shell[data-size='split'])) :is(.m-bar-x, .m-span-x) {
margin-left: var(--m-safe-l, 0px);
margin-right: var(--m-safe-r, 0px);
margin-inline: var(--m-safe-l, 0px) var(--m-safe-r, 0px);
}
html[dir='rtl']:not(:has(.m-shell[data-size='wide'], .m-shell[data-size='split'])) :is(.m-bar-x, .m-span-x) {
margin-inline: var(--m-safe-r, 0px) var(--m-safe-l, 0px);
}
/* A screen whose background is a map reaches under the rail: the map runs to
the window's edge and the rail floats over it like the top controls do. Its
+1 -1
View File
@@ -358,7 +358,7 @@ export function tripDayState(day: TripDay, nowMinutes: number, allDone: string):
}
/** How long before the day's first timed stop its Live Activity appears. */
export const LIVE_LEAD_MINUTES = 3 * 60;
const LIVE_LEAD_MINUTES = 3 * 60;
/**
* Whether the travel day's Live Activity belongs on the lock screen now: from
+6 -3
View File
@@ -104,10 +104,13 @@ export const NOT_PLURAL = [
{ key: 'dawarich.duration.hours', because: 'a duration in a unit symbol (h), the same for any number' },
{ key: 'dawarich.duration.hoursMinutes', because: 'a duration in unit symbols (h, min), the same for any number' },
{ key: 'files.uploadErrorSize', because: 'a size limit in a unit symbol (MB), the same for any number' },
{ key: 'native.plans.storage', because: 'a storage size in a unit symbol (GB), the same for any number' },
{
key: 'native.plans.aiDocs',
because: 'a monthly document allowance, always in the tens, so no singular ever shows',
key: 'native.plans.photos',
because: 'an estimate of photos a plan holds, always in the thousands, so no singular ever shows',
},
{
key: 'native.plans.aiPerMonth',
because: 'a monthly document allowance before a unit ("25 / month"), always in the tens',
},
];
+2 -2
View File
@@ -207,8 +207,8 @@ const native: TranslationStrings = {
'native.plans.billing': 'الدفع',
'native.claim.almost': 'اقتربنا',
'native.claim.addressField': 'العنوان',
'native.claim.slugPlaceholder': 'yourname', // same-as-en
'native.claim.emailPlaceholder': 'you@example.com', // same-as-en
'native.claim.slugPlaceholder': 'ismuka',
'native.claim.emailPlaceholder': 'anta@mithal.com',
'native.claim.passwordPlaceholder': 'اختر كلمة مرور',
'native.claim.freeBadge': 'متاح',
'native.claim.renews': 'يتجدّد تلقائيًا، ألغِ في أي وقت.',
+2 -2
View File
@@ -206,8 +206,8 @@ const native: TranslationStrings = {
'native.plans.billing': 'חיוב',
'native.claim.almost': 'כמעט שם',
'native.claim.addressField': 'כתובת',
'native.claim.slugPlaceholder': 'yourname', // same-as-en
'native.claim.emailPlaceholder': 'you@example.com', // same-as-en
'native.claim.slugPlaceholder': 'hashem-shelcha',
'native.claim.emailPlaceholder': 'ata@dugma.co.il',
'native.claim.passwordPlaceholder': 'בחרו סיסמה',
'native.claim.freeBadge': 'פנויה',
'native.claim.renews': 'מתחדש אוטומטית, ביטול בכל עת.',
+2 -2
View File
@@ -212,8 +212,8 @@ const native: TranslationStrings = {
'native.plans.billing': 'お支払い',
'native.claim.almost': 'もうすぐ到着',
'native.claim.addressField': 'アドレス',
'native.claim.slugPlaceholder': 'yourname', // same-as-en
'native.claim.emailPlaceholder': 'you@example.com', // same-as-en
'native.claim.slugPlaceholder': 'namae',
'native.claim.emailPlaceholder': 'anata@rei.jp',
'native.claim.passwordPlaceholder': 'パスワードを決める',
'native.claim.freeBadge': '空き',
'native.claim.renews': '自動更新、いつでも解約できます。',
+2 -2
View File
@@ -209,8 +209,8 @@ const native: TranslationStrings = {
'native.plans.billing': '결제',
'native.claim.almost': '거의 다 왔어요',
'native.claim.addressField': '주소',
'native.claim.slugPlaceholder': 'yourname', // same-as-en
'native.claim.emailPlaceholder': 'you@example.com', // same-as-en
'native.claim.slugPlaceholder': 'ireum',
'native.claim.emailPlaceholder': 'na@yesi.kr',
'native.claim.passwordPlaceholder': '비밀번호 정하기',
'native.claim.freeBadge': '사용 가능',
'native.claim.renews': '자동 갱신되며 언제든 해지할 수 있습니다.',
+2 -2
View File
@@ -205,8 +205,8 @@ const native: TranslationStrings = {
'native.plans.billing': 'การชำระเงิน',
'native.claim.almost': 'ใกล้ถึงแล้ว',
'native.claim.addressField': 'ที่อยู่',
'native.claim.slugPlaceholder': 'yourname', // same-as-en
'native.claim.emailPlaceholder': 'you@example.com', // same-as-en
'native.claim.slugPlaceholder': 'chue-khong-khun',
'native.claim.emailPlaceholder': 'khun@tuayang.co.th',
'native.claim.passwordPlaceholder': 'ตั้งรหัสผ่าน',
'native.claim.freeBadge': 'ว่าง',
'native.claim.renews': 'ต่ออายุอัตโนมัติ ยกเลิกได้ทุกเมื่อ',
+2 -2
View File
@@ -200,8 +200,8 @@ const native: TranslationStrings = {
'native.plans.billing': '付款',
'native.claim.almost': '快到了',
'native.claim.addressField': '網址',
'native.claim.slugPlaceholder': 'yourname', // same-as-en
'native.claim.emailPlaceholder': 'you@example.com', // same-as-en
'native.claim.slugPlaceholder': 'nidemingzi',
'native.claim.emailPlaceholder': 'ni@shili.tw',
'native.claim.passwordPlaceholder': '設定密碼',
'native.claim.freeBadge': '可用',
'native.claim.renews': '自動續訂,隨時可取消。',
+2 -2
View File
@@ -199,8 +199,8 @@ const native: TranslationStrings = {
'native.plans.billing': '付款',
'native.claim.almost': '马上就到',
'native.claim.addressField': '地址',
'native.claim.slugPlaceholder': 'yourname', // same-as-en
'native.claim.emailPlaceholder': 'you@example.com', // same-as-en
'native.claim.slugPlaceholder': 'nidemingzi',
'native.claim.emailPlaceholder': 'ni@shili.cn',
'native.claim.passwordPlaceholder': '设置密码',
'native.claim.freeBadge': '可用',
'native.claim.renews': '自动续订,随时可取消。',