From b14ba1725612ee5ddaa40626c4fcd32212f0cc7f Mon Sep 17 00:00:00 2001 From: tusooa Date: Sat, 14 Sep 2024 00:00:18 -0400 Subject: Support displaying time in absolute format This adds two config items: useAbsoluteTimeFormat (boolean) and absoluteTimeFormatMinAge (string, number + unit ('d'|'h'|'m'|'s')). When `useAbsoluteTimeFormat` is true, the Timeago component will display absolute time if the time is at least `absoluteTimeFormatMinAge` from now. If `longFormat` prop is true, the fully formatted time is displayed. Otherwise, the format is determined by the `time` prop: (1) if `time` is on the same day of now, display hour and minute; (2) if `time` is in the same month of now, display day and hour; (3) if `time` is in the same year of now, display month and day; (4) otherwise, display year and month. If it should display relative time, the format is the same as before. --- src/services/date_utils/date_utils.js | 43 +++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) (limited to 'src/services') diff --git a/src/services/date_utils/date_utils.js b/src/services/date_utils/date_utils.js index ed8e1417..69398c0c 100644 --- a/src/services/date_utils/date_utils.js +++ b/src/services/date_utils/date_utils.js @@ -6,10 +6,13 @@ export const WEEK = 7 * DAY export const MONTH = 30 * DAY export const YEAR = 365.25 * DAY -export const relativeTime = (date, nowThreshold = 1) => { +export const relativeTimeMs = (date) => { if (typeof date === 'string') date = Date.parse(date) + return Math.abs(Date.now() - date) +} +export const relativeTime = (date, nowThreshold = 1) => { const round = Date.now() > date ? Math.floor : Math.ceil - const d = Math.abs(Date.now() - date) + const d = relativeTimeMs(date) const r = { num: round(d / YEAR), key: 'time.unit.years' } if (d < nowThreshold * SECOND) { r.num = 0 @@ -57,3 +60,39 @@ export const secondsToUnit = (unit, amount) => { case 'days': return (1000 * amount) / DAY } } + +export const isSameYear = (a, b) => { + return a.getFullYear() === b.getFullYear() +} + +export const isSameMonth = (a, b) => { + return a.getFullYear() === b.getFullYear() && + a.getMonth() === b.getMonth() +} + +export const isSameDay = (a, b) => { + return a.getFullYear() === b.getFullYear() && + a.getMonth() === b.getMonth() && + a.getDate() === b.getDate() +} + +export const durationStrToMs = (str) => { + if (typeof str !== 'string') { + return 0 + } + + const unit = str.replace(/[0-9,.]+/, '') + const value = str.replace(/[^0-9,.]+/, '') + switch (unit) { + case 'd': + return value * DAY + case 'h': + return value * HOUR + case 'm': + return value * MINUTE + case 's': + return value * SECOND + default: + return 0 + } +} -- cgit v1.2.3-70-g09d2 From 1794d52731607baa3f80ea6a5ab2dbac5bd747ef Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Thu, 19 Sep 2024 15:43:38 +0300 Subject: changelog --- changelog.d/browsers-support.change | 9 +++++ src/services/theme_data/iss_serializer.js | 62 +++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 changelog.d/browsers-support.change create mode 100644 src/services/theme_data/iss_serializer.js (limited to 'src/services') diff --git a/changelog.d/browsers-support.change b/changelog.d/browsers-support.change new file mode 100644 index 00000000..a62e5024 --- /dev/null +++ b/changelog.d/browsers-support.change @@ -0,0 +1,9 @@ +Updated our build system to support browsers: + Safari >= 15 + Firefox >= 115 + Android > 4 + no Opera Mini support + no IE support + no "dead" (unmaintained) browsers support + +This does not guarantee that browsers will or will not work. diff --git a/src/services/theme_data/iss_serializer.js b/src/services/theme_data/iss_serializer.js new file mode 100644 index 00000000..39151e41 --- /dev/null +++ b/src/services/theme_data/iss_serializer.js @@ -0,0 +1,62 @@ +import { unroll } from './iss_utils' + +const getCanonicState = (state) => { + if (state) { + return ['normal', ...state.filter(x => x !== 'normal')] + } else { + return ['normal'] + } +} + +const getCanonicRuleHeader = ({ + component, + variant = 'normal', + parent, + state +}) => ({ + component, + variant, + parent, + state: getCanonicState(state) +}) + +const prepareRule = (rule) => { + const { parent } = rule + const chain = [...unroll(parent), rule].map(getCanonicRuleHeader) + const header = chain.map(({ component, variant, state }) => [ + component, + variant === 'normal' ? '' : ('.' + variant), + state.filter(s => s !== 'normal').map(s => ':' + s).join('') + ].join('')).join(' ') + + console.log(header, rule.directives) + const content = Object.entries(rule.directives).map(([key, value]) => { + let realValue = value + + switch (key) { + case 'shadow': + realValue = realValue.map(v => `${v.inset ? 'inset ' : ''}${v.x} ${v.y} ${v.blur} ${v.spread} ${v.color} / ${v.alpha}`) + } + + if (Array.isArray(realValue)) { + realValue = realValue.join(', ') + } + + return ` ${key}: ${realValue};` + }).sort().join('\n') + + return [ + header, + content + ] +} + +export const serialize = (ruleset) => { + // Scrapped idea: automatically combine same-set directives + // problem: might violate the order rules + + return ruleset.filter(r => Object.keys(r.directives).length > 0).map(r => { + const [header, content] = prepareRule(r) + return `${header} {\n${content}\n}\n\n` + }) +} -- cgit v1.2.3-70-g09d2