From a77c6f37d0758f2ff4037fde91e1920c50c2ce9d Mon Sep 17 00:00:00 2001 From: Taras Perun Date: Mon, 14 Aug 2023 12:47:07 +0200 Subject: [PATCH 1/9] add getStatusUntilDate --- src/libs/DateUtils.js | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/libs/DateUtils.js b/src/libs/DateUtils.js index 6be627dc643d..b0087eb6d93b 100644 --- a/src/libs/DateUtils.js +++ b/src/libs/DateUtils.js @@ -205,6 +205,38 @@ function getDateStringFromISOTimestamp(isoTimestamp) { return dateString; } +/** + * receive date like 2020-05-16 05:34:14 and format it to show in string like "Until 05:34 PM" + * + * @param {String} inputDate + * @returns {String} + */ +function getStatusUntilDate(inputDate) { + if (!inputDate) return ''; + + const input = moment(inputDate, 'YYYY-MM-DD HH:mm:ss'); + const now = moment(); + const endOfToday = moment().endOf('day').format('YYYY-MM-DD HH:mm:ss'); + + // If the date is equal to the end of today + if (input.isSame(endOfToday)) { + return 'Until tomorrow'; + } + + // If it's a time on the same date + if (input.isSame(now, 'day')) { + return `Until ${input.format('hh:mm A')}`; + } + + // If it's further in the future than tomorrow but within the same year + if (input.isAfter(now) && input.isSame(now, 'year')) { + return `Until ${input.format('MM-DD hh:mm A')}`; + } + + // If it's in another year + return `Until ${input.format('YYYY-MM-DD hh:mm A')}`; +} + /** * @namespace DateUtils */ @@ -220,6 +252,7 @@ const DateUtils = { getDBTime, subtractMillisecondsFromDateTime, getDateStringFromISOTimestamp, + getStatusUntilDate, }; export default DateUtils; From 6ed5ca6e34756f27ae200f691b06255998891b31 Mon Sep 17 00:00:00 2001 From: Taras Perun Date: Mon, 14 Aug 2023 12:48:54 +0200 Subject: [PATCH 2/9] fix saving clearAfter date --- src/pages/settings/Profile/CustomStatus/StatusPage.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/settings/Profile/CustomStatus/StatusPage.js b/src/pages/settings/Profile/CustomStatus/StatusPage.js index 9767825820cd..061997e79044 100644 --- a/src/pages/settings/Profile/CustomStatus/StatusPage.js +++ b/src/pages/settings/Profile/CustomStatus/StatusPage.js @@ -38,8 +38,8 @@ function StatusPage({draftStatus, currentUserPersonalDetails}) { const hasDraftStatus = !!draftEmojiCode || !!draftText; const updateStatus = useCallback(() => { - const endOfDay = moment().endOf('day').toDate(); - User.updateCustomStatus({text: defaultText, emojiCode: defaultEmoji, clearAfter: endOfDay.toISOString()}); + const endOfDay = moment().endOf('day').format('YYYY-MM-DD HH:mm:ss'); + User.updateCustomStatus({text: defaultText, emojiCode: defaultEmoji, clearAfter: endOfDay}); User.clearDraftCustomStatus(); Navigation.goBack(ROUTES.SETTINGS); From ac5ef688946b3be6c2ea0d1e09323034b791b4ae Mon Sep 17 00:00:00 2001 From: Taras Perun Date: Mon, 14 Aug 2023 12:57:45 +0200 Subject: [PATCH 3/9] add emoji next to avatar --- src/libs/DateUtils.js | 36 +++++++++---------- .../home/report/ReportActionItemSingle.js | 30 ++++++++++++++-- src/styles/styles.js | 5 +++ 3 files changed, 51 insertions(+), 20 deletions(-) diff --git a/src/libs/DateUtils.js b/src/libs/DateUtils.js index b0087eb6d93b..04bd32c5b98a 100644 --- a/src/libs/DateUtils.js +++ b/src/libs/DateUtils.js @@ -212,29 +212,29 @@ function getDateStringFromISOTimestamp(isoTimestamp) { * @returns {String} */ function getStatusUntilDate(inputDate) { - if (!inputDate) return ''; + if (!inputDate) return ''; - const input = moment(inputDate, 'YYYY-MM-DD HH:mm:ss'); - const now = moment(); - const endOfToday = moment().endOf('day').format('YYYY-MM-DD HH:mm:ss'); + const input = moment(inputDate, 'YYYY-MM-DD HH:mm:ss'); + const now = moment(); + const endOfToday = moment().endOf('day').format('YYYY-MM-DD HH:mm:ss'); - // If the date is equal to the end of today - if (input.isSame(endOfToday)) { - return 'Until tomorrow'; - } + // If the date is equal to the end of today + if (input.isSame(endOfToday)) { + return 'Until tomorrow'; + } - // If it's a time on the same date - if (input.isSame(now, 'day')) { - return `Until ${input.format('hh:mm A')}`; - } + // If it's a time on the same date + if (input.isSame(now, 'day')) { + return `Until ${input.format('hh:mm A')}`; + } - // If it's further in the future than tomorrow but within the same year - if (input.isAfter(now) && input.isSame(now, 'year')) { - return `Until ${input.format('MM-DD hh:mm A')}`; - } + // If it's further in the future than tomorrow but within the same year + if (input.isAfter(now) && input.isSame(now, 'year')) { + return `Until ${input.format('MM-DD hh:mm A')}`; + } - // If it's in another year - return `Until ${input.format('YYYY-MM-DD hh:mm A')}`; + // If it's in another year + return `Until ${input.format('YYYY-MM-DD hh:mm A')}`; } /** diff --git a/src/pages/home/report/ReportActionItemSingle.js b/src/pages/home/report/ReportActionItemSingle.js index 8633f8f8a224..d7fc3be593e2 100644 --- a/src/pages/home/report/ReportActionItemSingle.js +++ b/src/pages/home/report/ReportActionItemSingle.js @@ -3,6 +3,7 @@ import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; import PropTypes from 'prop-types'; import _ from 'underscore'; +import {withOnyx} from 'react-native-onyx'; import reportActionPropTypes from './reportActionPropTypes'; import ReportActionItemFragment from './ReportActionItemFragment'; import styles from '../../../styles/styles'; @@ -26,6 +27,11 @@ import UserDetailsTooltip from '../../../components/UserDetailsTooltip'; import MultipleAvatars from '../../../components/MultipleAvatars'; import * as StyleUtils from '../../../styles/StyleUtils'; import themeColors from '../../../styles/themes/default'; +import Permissions from '../../../libs/Permissions'; +import ONYXKEYS from '../../../ONYXKEYS'; +import Text from '../../../components/Text'; +import Tooltip from '../../../components/Tooltip'; +import DateUtils from '../../../libs/DateUtils'; const propTypes = { /** All the data of the action */ @@ -84,7 +90,7 @@ const showWorkspaceDetails = (reportID) => { function ReportActionItemSingle(props) { const actorAccountID = props.action.actorAccountID; let {displayName} = props.personalDetailsList[actorAccountID] || {}; - const {avatar, login, pendingFields} = props.personalDetailsList[actorAccountID] || {}; + const {avatar, login, pendingFields, status} = props.personalDetailsList[actorAccountID] || {}; let actorHint = (login || displayName || '').replace(CONST.REGEX.MERGED_ACCOUNT_PREFIX, ''); const isWorkspaceActor = ReportUtils.isPolicyExpenseChat(props.report) && !actorAccountID; let avatarSource = UserUtils.getAvatar(avatar, actorAccountID); @@ -189,6 +195,10 @@ function ReportActionItemSingle(props) { ); }; + const hasEmojiStatus = !displayAllActors && status && status.emojiCode && Permissions.canUseCustomStatus(props.betas); + const formattedDate = DateUtils.getStatusUntilDate(lodashGet(status, 'clearAfter')); + const statusText = lodashGet(status, 'text', ''); + const statusTooltipText = formattedDate ? `${statusText} (${formattedDate})` : statusText; return ( @@ -228,6 +238,14 @@ function ReportActionItemSingle(props) { /> ))} + {!!hasEmojiStatus && ( + + {`${status.emojiCode}`} + + )} ) : null} @@ -241,4 +259,12 @@ ReportActionItemSingle.propTypes = propTypes; ReportActionItemSingle.defaultProps = defaultProps; ReportActionItemSingle.displayName = 'ReportActionItemSingle'; -export default compose(withLocalize, withPersonalDetails())(ReportActionItemSingle); +export default compose( + withLocalize, + withPersonalDetails(), + withOnyx({ + betas: { + key: ONYXKEYS.BETAS, + }, + }), +)(ReportActionItemSingle); diff --git a/src/styles/styles.js b/src/styles/styles.js index 2d5514d6df39..25e0a76ea874 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -3681,6 +3681,11 @@ const styles = { rotate90: { transform: [{rotate: '90deg'}], }, + + userReportStatusEmoji: { + fontSize: variables.fontSizeNormal, + marginRight: 4, + }, }; export default styles; From 6cb772e2821eaa6822bcd7543b45360cce2f6742 Mon Sep 17 00:00:00 2001 From: Taras Perun Date: Tue, 15 Aug 2023 15:00:38 +0200 Subject: [PATCH 4/9] translations --- src/languages/en.js | 2 ++ src/languages/es.js | 2 ++ src/libs/DateUtils.js | 9 +++++---- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/languages/en.js b/src/languages/en.js index 09651e6ec05e..5aca4261496f 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -874,6 +874,8 @@ export default { clearStatus: 'Clear status', save: 'Save', message: 'Message', + untilTomorrow: 'Until tomorrow', + untilTime: ({time}) => `Until ${time}`, }, stepCounter: ({step, total, text}) => { let result = `Step ${step}`; diff --git a/src/languages/es.js b/src/languages/es.js index fa920c84ce35..2d1929c857de 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -878,6 +878,8 @@ export default { clearStatus: 'Borrar estado', save: 'Guardar', message: 'Mensaje', + untilTomorrow: 'Hasta mañana', + untilTime: ({time}) => `Hasta las ${time}`, }, stepCounter: ({step, total, text}) => { let result = `Paso ${step}`; diff --git a/src/libs/DateUtils.js b/src/libs/DateUtils.js index 04bd32c5b98a..4115e8f1b9e3 100644 --- a/src/libs/DateUtils.js +++ b/src/libs/DateUtils.js @@ -213,6 +213,7 @@ function getDateStringFromISOTimestamp(isoTimestamp) { */ function getStatusUntilDate(inputDate) { if (!inputDate) return ''; + const {translateLocal} = Localize; const input = moment(inputDate, 'YYYY-MM-DD HH:mm:ss'); const now = moment(); @@ -220,21 +221,21 @@ function getStatusUntilDate(inputDate) { // If the date is equal to the end of today if (input.isSame(endOfToday)) { - return 'Until tomorrow'; + return translateLocal('statusPage.untilTomorrow'); } // If it's a time on the same date if (input.isSame(now, 'day')) { - return `Until ${input.format('hh:mm A')}`; + return translateLocal('statusPage.untilTime', {time: input.format('hh:mm A')}); } // If it's further in the future than tomorrow but within the same year if (input.isAfter(now) && input.isSame(now, 'year')) { - return `Until ${input.format('MM-DD hh:mm A')}`; + return translateLocal('statusPage.untilTime', {time: input.format('MM-DD hh:mm A')}); } // If it's in another year - return `Until ${input.format('YYYY-MM-DD hh:mm A')}`; + return translateLocal('statusPage.untilTime', {time: input.format('YYYY-MM-DD hh:mm A')}); } /** From 99b9ca0db63b236f3ac8b8c2df6da7844752880b Mon Sep 17 00:00:00 2001 From: Taras Perun Date: Tue, 15 Aug 2023 20:13:39 +0200 Subject: [PATCH 5/9] use Boolean() --- src/pages/home/report/ReportActionItemSingle.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/report/ReportActionItemSingle.js b/src/pages/home/report/ReportActionItemSingle.js index d7fc3be593e2..c00f98c613e4 100644 --- a/src/pages/home/report/ReportActionItemSingle.js +++ b/src/pages/home/report/ReportActionItemSingle.js @@ -238,7 +238,7 @@ function ReportActionItemSingle(props) { /> ))} - {!!hasEmojiStatus && ( + {Boolean(hasEmojiStatus) && ( Date: Wed, 16 Aug 2023 10:02:08 +0200 Subject: [PATCH 6/9] change translations --- src/languages/es.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/languages/es.js b/src/languages/es.js index 2d1929c857de..29d21a49fe8d 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -879,7 +879,7 @@ export default { save: 'Guardar', message: 'Mensaje', untilTomorrow: 'Hasta mañana', - untilTime: ({time}) => `Hasta las ${time}`, + untilTime: ({time}) => `Hasta la ${time}`, }, stepCounter: ({step, total, text}) => { let result = `Paso ${step}`; From 89939538c7d80c2b45a96aae832edb91ae9ed9c7 Mon Sep 17 00:00:00 2001 From: Taras Perun Date: Wed, 16 Aug 2023 19:13:20 +0200 Subject: [PATCH 7/9] update es translations --- src/languages/es.js | 18 +++++++++++++++++- src/libs/RegExp.js | 11 +++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/libs/RegExp.js diff --git a/src/languages/es.js b/src/languages/es.js index 29d21a49fe8d..6de49b3a5f16 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -1,5 +1,6 @@ import CONST from '../CONST'; import * as ReportActionsUtils from '../libs/ReportActionsUtils'; +import RegExp from '../libs/RegExp'; /* eslint-disable max-len */ export default { @@ -879,7 +880,22 @@ export default { save: 'Guardar', message: 'Mensaje', untilTomorrow: 'Hasta mañana', - untilTime: ({time}) => `Hasta la ${time}`, + untilTime: ({time}) => { + // Check for HH:MM AM/PM format and starts with '01:' + if (RegExp.TIME_STARTS_01.test(time)) { + return `Hasta la ${time}`; + } + // Check for HH:MM AM/PM format and starts with '11:' + if (RegExp.TIME_STARTS_11.test(time)) { + return `Hasta las ${time}`; + } + // Check for 06-29 11:30AM format + if (RegExp.DATE_TIME_FORMAT.test(time)) { + return `Hasta el día ${time}`; + } + // Default case + return `Hasta ${time}`; + }, }, stepCounter: ({step, total, text}) => { let result = `Paso ${step}`; diff --git a/src/libs/RegExp.js b/src/libs/RegExp.js new file mode 100644 index 000000000000..f084d9ac2317 --- /dev/null +++ b/src/libs/RegExp.js @@ -0,0 +1,11 @@ +const TIME_STARTS_01 = /^01:\d{2} [AP]M$/; +const TIME_STARTS_11 = /^11:\d{2} [AP]M$/; +const DATE_TIME_FORMAT = /^\d{2}-\d{2} \d{2}:\d{2}[AP]M$/; + +const RegExpPatterns = { + TIME_STARTS_01, + TIME_STARTS_11, + DATE_TIME_FORMAT +}; + +export default RegExpPatterns; From b002bf6df62537d9ea78d49f5e39dfec9e144895 Mon Sep 17 00:00:00 2001 From: Taras Perun Date: Wed, 16 Aug 2023 19:33:27 +0200 Subject: [PATCH 8/9] fix regExp --- src/languages/es.js | 6 +++--- src/libs/RegExp.js | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/languages/es.js b/src/languages/es.js index 6de49b3a5f16..b56b831d5d92 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -885,11 +885,11 @@ export default { if (RegExp.TIME_STARTS_01.test(time)) { return `Hasta la ${time}`; } - // Check for HH:MM AM/PM format and starts with '11:' - if (RegExp.TIME_STARTS_11.test(time)) { + // Check for any HH:MM AM/PM format not starting with '01:' + if (RegExp.TIME_FORMAT.test(time)) { return `Hasta las ${time}`; } - // Check for 06-29 11:30AM format + // Check for date-time format like "06-29 11:30 AM" if (RegExp.DATE_TIME_FORMAT.test(time)) { return `Hasta el día ${time}`; } diff --git a/src/libs/RegExp.js b/src/libs/RegExp.js index f084d9ac2317..566a551501ee 100644 --- a/src/libs/RegExp.js +++ b/src/libs/RegExp.js @@ -1,10 +1,10 @@ const TIME_STARTS_01 = /^01:\d{2} [AP]M$/; -const TIME_STARTS_11 = /^11:\d{2} [AP]M$/; -const DATE_TIME_FORMAT = /^\d{2}-\d{2} \d{2}:\d{2}[AP]M$/; +const TIME_FORMAT = /^\d{2}:\d{2} [AP]M$/; +const DATE_TIME_FORMAT = /^\d{2}-\d{2} \d{2}:\d{2} [AP]M$/; const RegExpPatterns = { TIME_STARTS_01, - TIME_STARTS_11, + TIME_FORMAT, DATE_TIME_FORMAT }; From 6ff5f6a2ae9789c4b17759bff8e006872adeec31 Mon Sep 17 00:00:00 2001 From: Taras Perun Date: Wed, 16 Aug 2023 20:50:49 +0200 Subject: [PATCH 9/9] move regExp to const --- src/CONST.js | 4 ++++ src/languages/es.js | 7 +++---- src/libs/RegExp.js | 11 ----------- 3 files changed, 7 insertions(+), 15 deletions(-) delete mode 100644 src/libs/RegExp.js diff --git a/src/CONST.js b/src/CONST.js index 4c19965837d9..ab796da44464 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -181,6 +181,10 @@ const CONST = { // If the length is longer than 13 digits, we show the first 6 and last 4 digits, hiding the rest with X MASKED_US_ACCOUNT_NUMBER: /^[X]{0,9}[0-9]{4}$|^[0-9]{6}[X]{4,7}[0-9]{4}$/, SWIFT_BIC: /^[A-Za-z0-9]{8,11}$/, + + TIME_STARTS_01: /^01:\d{2} [AP]M$/, + TIME_FORMAT: /^\d{2}:\d{2} [AP]M$/, + DATE_TIME_FORMAT: /^\d{2}-\d{2} \d{2}:\d{2} [AP]M$/, }, VERIFICATION_MAX_ATTEMPTS: 7, STATE: { diff --git a/src/languages/es.js b/src/languages/es.js index b56b831d5d92..88d3a3137fbd 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -1,6 +1,5 @@ import CONST from '../CONST'; import * as ReportActionsUtils from '../libs/ReportActionsUtils'; -import RegExp from '../libs/RegExp'; /* eslint-disable max-len */ export default { @@ -882,15 +881,15 @@ export default { untilTomorrow: 'Hasta mañana', untilTime: ({time}) => { // Check for HH:MM AM/PM format and starts with '01:' - if (RegExp.TIME_STARTS_01.test(time)) { + if (CONST.REGEX.TIME_STARTS_01.test(time)) { return `Hasta la ${time}`; } // Check for any HH:MM AM/PM format not starting with '01:' - if (RegExp.TIME_FORMAT.test(time)) { + if (CONST.REGEX.TIME_FORMAT.test(time)) { return `Hasta las ${time}`; } // Check for date-time format like "06-29 11:30 AM" - if (RegExp.DATE_TIME_FORMAT.test(time)) { + if (CONST.REGEX.DATE_TIME_FORMAT.test(time)) { return `Hasta el día ${time}`; } // Default case diff --git a/src/libs/RegExp.js b/src/libs/RegExp.js deleted file mode 100644 index 566a551501ee..000000000000 --- a/src/libs/RegExp.js +++ /dev/null @@ -1,11 +0,0 @@ -const TIME_STARTS_01 = /^01:\d{2} [AP]M$/; -const TIME_FORMAT = /^\d{2}:\d{2} [AP]M$/; -const DATE_TIME_FORMAT = /^\d{2}-\d{2} \d{2}:\d{2} [AP]M$/; - -const RegExpPatterns = { - TIME_STARTS_01, - TIME_FORMAT, - DATE_TIME_FORMAT -}; - -export default RegExpPatterns;